咱这里先声明下,面向接口编程并不是一种新的编程范式,咱这里说的是狭义的接口,也就是interface关键字。之后,咱们就先来看下接口的作用。
接口,主要是定义一套规范,来描述一个“物”的功能,要求如果现实中的“物”想成为可用的,就必须实现某些基本功能。可以这么理解:对于实现接口的所有类,看起来都应该与接口类似。
接口常用来作为类与类之间的一个协议,可以说接口是抽象类的变体,其中所有的方法都是抽象的,没有一个程序体。
接口除了可以包含方法外,还可以包含常量。
我们来举个栗子描述下接口,使用接口描述机动车。
我们想要判断机动车是否合格,至于什么车(怎么实现),前轮还是后轮(程序是什么样子),这些都不是接口需要关心的,因为接口为抽象而生,我们要判断这辆车是否合格,只需要按着接口的定义,一条条的验证,有不符合定义的,那么这辆车,就是废品,如果没有,那就合格,至于这辆车装修是否豪华,跟我们没有关系的。
说白了,接口就是一种契约,在程序里,接口的方法必须被全部实现,否则,将会报一个致命错误。来看一段代码感受下效果:
interface car{
public function body();
}
class baoma implements car{
public function body()
{
// TODO: Implement body() method.
echo "i am baoma";
}
}
class aodi implements car{
public function body()
{
// TODO: Implement body() method.
echo "i am aodi";
}
public function title()
{
echo "i am aodi title";
}
}
class benchi{
public function title(car $a)
{
$a->title();
}
}
$obj = new benchi();
$obj->title(new baoma());
$obj->title(new aodi());
上述代码中,我们定义了一个car接口,内含一个body功能,之后用baoma和aodi类来实现这个接口,并且在aodi中新增一个title功能,之后我们在benchi类中使用类型约束指定要检测的是car这个接口,但是car里面并没有title这个功能,所以,就会报错。
很明显我们可以看出来,这段代码是错误的,因为它不符合接口的语义。
但是嘞,在PHP里,我们来对aodi这个类来检测的时候,却是可以正常运行的。
我们可以看出来,PHP它本身只关心这个继承接口的类是否实现了接口中的所有方法,而不关心这个代码的接口语义是否正确。
按着道理来讲,接口应该起一个强制规范和契约的作用,但是上述代码对接口的约束并没有起作用,也打破了契约。废话不多说,咱们来看下在Java中是如何来处理上述情况的。
Java认为呢,接口就是一种type,也就是说类型,如果你继承了我的接口,完事又打破了你我之间的契约,那么你的行为我就无法控制了,所以你就是非法的。符合逻辑吧。。。
接口呢,不仅规范接口的实现者,还会规范接口的执行者,它不允许调用接口中不存在的方法。
当然啦,这不是说一个类,如果实现了接口,就只能实现接口中含有的方法,它的意思是,如果针对接口,而不是具体的类,就只能按着接口的契约办事。
这种规范呢,对于我们使用接口是非常有利的,它可以让我们的程序更加健壮,从这个角度来看的话,为了保证接口的语义,通常一个接口的实现类只是实现该接口所具有的方法,做到专一,当然,这不是一成不变的。
通常在大的项目里,我们会把代码进行分层和分工,例如,核心开发人员和技术经理编写核心的流程和代码,往往是以接口的形式给出,之后就是基层开发人员针对这些接口来进行像数据库操作之类的代码填充,这样一来,核心技术人员就可以把更多的精力投入到技术攻关和业务逻辑中。
通常情况就是,前端针对接口编程的话,只管在actioncen层次调用server的服务,而不管具体的实现细节,对于后端的开发人员来说,就只需要负责实现server层次的业务就好,这样,就实现了代码的分工与合作。
在这里咱再提一嘴啊,接口本身并不提供实现,它只是提供一个规范,比如我们知道某个类实现了某个接口,我们就可以知道,在这个类中,我们可以调用哪些方法,但是,在PHP中,接口的语义是有限的,使用接口的地方并不多,我们可以将其淡化为设计文档,起到一个团队基本契约的作用。
好啦,这篇文章咱就不废话了啊,敬请期待后续文章。
如果感觉不错的话,请多多点赞支持哦。。。