语法上的区别是接口的使用是通过关键字implements,定义是通过关键字interface;抽象类的使用是通过关键字extends(当然接口也是可以通过关键字extends继承的),定义就是使用关键字abstractclass。接口只有常量和方法,抽象类包含了普通类的所有机制。接口中的方法必须是公共类型,而抽象类则不受限制。一个类可以同时实现多个接口,但是一个类只能继承一个抽象类。有方法体的普通方法可以定义在抽象类中,但接口不能相同。接口中的方法和抽象类中的抽象方法都不能有方法体,必须在其子类中实现,可以继承但不能实例化适用场景如果要创建一个模型,将被采用一些密切相关的对象,可以使用抽象类。当您想要创建将被一些不相关的对象采用的功能时,将使用接口。当必须从多个源继承行为时,使用接口。如果您知道所有类都将共享一个公共行为实现,请使用抽象类并在其中实现该行为。代码示例以下代码摘自闫十八公益课堂/*春秋战国时期,闫令奇是飞行器专家,也是能工巧匠。他写了一张蓝图---飞行器制造技术飞行器秘图1:必须有一个强大的引擎,喷气式。2:要有平衡舵,掌握平衡。他的孙子问:如何制造发动机?燕灵琪望着夕阳:我做不出来,但我相信未来有人做出燕灵琪当时的想法,用先进的科技是无法创造出来的,也就是只能创造出这个班级在图纸中,不能实例化。***///这个时候这个类没有具体的方法实现,太抽象了。//所以我们把它做成一个抽象类abstractclassFlyIdea{//强大的引擎,当时做不到,这个方法实现不了,所以方法也是抽象的publicabstractfunctionengine();//平衡舵publicabstractfunctionblance();/*注意:abstract方法不能有方法体。错误的写法如下publicabstractfunctionblance(){}Fatalerror:AbstractfunctionFlyIdea::engine()cannotcontainbody*/}/*Theabstractclasscannotbeinstantiatedwithnew下面一行是错误$kongke=新的FlyIdea();无法实例化抽象类FlyIdea*///明代万户用火箭解决发动机问题火药,失去平衡,砰!
';}//但是万户不能实现平衡舵,所以平衡舵对于Rocket类来说还是抽象的,该类也是抽象的//这里,由于父类的继承也是抽象类,所以是没有必要在抽象类中完成所有的抽象方法;}/*在现代,严十八在Fly类中自己制作了飞机,所以有了抽象的方法,已经实现了,不再是梦想。*///当你到达这个类时,你必须完成所有的抽象方法;classFlyextendsRocket{publicfunctionengine(){echo'powerfulthrow
';}publicfunctionblance(){echo'两只纸翅膀保持平衡~~~';}publicfunctionstart(){$this->engine();对于($i=0;$i<10;$i++){$this->blance();echo'顺利飞行
';}}}$apache=newFly();$apache->开始();抽象是某类对象的蓝图。举个例子:女娲造人的时候,她心目中的人形象就是人类Human。如果,当初女娲决定造人,形象还没有定型,那她脑海中的哪些碎片化的形象呢?她可能会这样想:动物:吃猴子:奔跑的猴子:自己哭泣:想鸟:飞翔我创造了一个生物,命名为人类,它应该具有以下功能eat()run();哭();思考();如果说类是对事物/动物的抽象,那么接口就是对事物/动物的功能的抽象,即将其功能分成小块,自由组合成新的特殊类型*/;界面动物{constNAME='zxg';//不能定义属性,但可以定义常量;公共功能吃();}interfacemonkey{publicfunctionrun();公共功能哭泣();}interfacewisdom{publicfunctionthink();}interfacebird{publicfunctionfly();}/*和上面一样,我们把这个实现放在每个类中函数拆解分析:如果有一个新的生物实现eat()+run()+cry()+think(),这个智能生物就可以称为人类。classHumanimplementsanimal,monkey,wisdom{}Humanclassanimal、monkey、wisdom接口中的方法必须包含,缺一不可,否则会报错。Human类包含4个抽象方法*/classHumanimplementsanimal,monkey,wisdom,bird{//这里的接口数量可以随意增加;添加后该类中的方法必须有新增接口中的方法publicfunctioneat(){echo"eatingmethod";}publicfunctionrun(){echoself::NAME;//可以通过self访问任意接口定义的常量;echo'步行法';}publicfunctioncry(){echo'哭法';}publicfunctionthink(){echoanimal::NAME;//也可以传接口名echo'Thinkingmethod';}publicfunctionsmile(){echo"这是新添加的smile方法";}publicfunctionfly(){echo"这是接口bird中新添加的fly方法";}}$obj=newHuman();$obj->think();/***====注释====一个面向对象的观点:越做越容易出错抽象类{定义一个类模板即可}--具体子类实现{china,japan,english}接口:***///抽象数据库类/*创业公司网站用的是什么数据库?mysql、oracle、sqlserver、postgresql?这样:先把网站开发好,再谈运营。先弄个mysql开发,等正式上线再改数据库也不迟。提出一个问题:换数据库是不是要重写之前的代码?答:不能,使用抽象类的开发者在开发的时候应该用db抽象类来开发。*/abstractclassdb{publicabstractfunctionconnect($h,$u,$p);公共抽象函数查询($sql);公共抽象函数关闭();}/*//下面的代码是错误的//因为子类实现的时候,connect和抽象类connect的参数不一致classmysqlextendsdb{publicfunctionconnect($h,$h){returntrue;}publicfunctionquery($sql,$conn){}publicfunctionclose(){}}*//*下面的mysql类,严格实现了db抽象类想象一下:不管上线时实际使用什么数据库,我只需要写下面的类classoracleextendsdb{}classmssqlextendsdb{}classpostsqlextendsdb{}业务逻辑层不用改?为什么不改变呢?因为实现了db抽象类。我开发的时候,调用方法不清楚的时候可以参考db抽象类。不管怎样,子类都是严格实现的抽象类。*/classmysqlextendsdb{publicfunctionconnect($h,$h,$u){返回真;}publicfunctionquery($sql){}publicfunctionclose(){}}/*接口比较抽象,比如一个社交网站,关于用户处理是核心应用。登录、注销、写信、读信、打招呼、换心情、吃饭骂人、闹事、秀恩爱、调侃的方法那么多,都是用户的方法。自然可以自己写一个用户类,全部封装起来。但是,一次性分析用户不能使用这种方法。用户信息类:{login,write,read,greet,changemood,exit}用户娱乐类:{login,scold,trouble,showlove,flirt,exit}开发网站之前,分析了这么多方法,但是他们不能都装在一个档次里,分成两个档次,甚至更多。在应用逻辑的开发中,那么多的类,那么多的方法,看得头晕目眩。*/interfaceUserBase{publicfunctionlogin($u,$p);公共功能注销();}interfaceUserMsg{publicfunctionwirteMsg($to,$title,$content);公共函数readMsg($from,$title);}interfaceUserFun{publicfunctionspit($to);公共功能showLove($to);}/*ascall或者,我不需要知道你的用户信息类,用户娱乐类,我可以知道如何调用这两个类,因为:这两个类必须实现上面的接口。通过这个接口,可以规范开发。*//*下面的类和接口声明的参数不一样,会报错。这样,接口就强制统一了类的功能。不管你有多少个类,我只知道一个类有多少个方法。这些方法都是已实现的接口。方法。*/classUserimplementsUserBase{publicfunctionlogin($u){}}
