接口允许您创建定义实现接口的类的方法的代码。但是,您不能向这些方法添加任何代码。

抽象类允许您做同样的事情,同时向方法添加代码。

现在,如果可以用抽象类实现同样的目标,我们为什么还需要接口的概念呢?

有人告诉我,这与从c++到Java的面向对象理论有关,这也是PHP面向对象的基础。这个概念在Java中有用而在PHP中没有吗?这仅仅是一种避免在抽象类中布满占位符的方法吗?我遗漏了什么吗?


当前回答

界面就像你的基因。

抽象类就像你实际的父母。

它们的目的是遗传的,但是在抽象类和接口的情况下,继承的是更具体的。

其他回答

对我来说,使用接口和抽象类之间的区别更多地与代码组织有关,而不是由语言本身强制执行。在为其他开发人员准备代码时,我经常使用它们,以便它们保持在预期的设计模式内。接口是一种“契约式设计”,您的代码同意响应一组规定的API调用,这些API调用可能来自您没有访问权限的代码。

虽然从抽象类继承是一个“是一个”关系,但这并不总是你想要的,实现接口更像是一个“像一个”关系。在某些情况下,这种差异可能相当显著。

例如,假设您有一个抽象类Account,许多其他类都是从这个抽象类扩展而来的(Account的类型等等)。它有一组特定的方法,只适用于该类型组。但是,这些帐户子类中的一些实现了Versionable、Listable或Editable,以便它们可以被扔到期望使用这些api的控制器中。控制器并不关心对象的类型

相比之下,我还可以创建一个不从Account扩展的对象,比如User抽象类,仍然实现Listable和Editable,但不实现Versionable,这在这里没有意义。

通过这种方式,我说FooUser子类不是一个帐户,但确实像一个可编辑对象。同样,BarAccount从Account扩展而来,但不是User子类,而是实现了可编辑、可列表和可版本。

将所有这些可编辑的、可列表的和可版本的api添加到抽象类本身不仅是混乱和丑陋的,而且会重复Account和User中的公共接口,或者强制我的User对象实现Versionable,可能只是抛出一个异常。

接口本质上是您可以创建的内容的蓝图。它们定义了类必须具有的方法,但是您可以在这些限制之外创建额外的方法。

我不确定你所说的不能向方法添加代码是什么意思——因为你可以。您是将接口应用到抽象类还是扩展它的类?

应用于抽象类的接口中的方法需要在该抽象类中实现。然而,将该接口应用于扩展类,该方法只需要在扩展类中实现。在这里我可能错了——我没有尽可能多地使用接口。

我一直认为接口是外部开发人员的一种模式,或者是确保事情正确的额外规则集。

这个概念在面向对象编程中非常有用。对我来说,我认为接口是一种契约。只要我的类和你的类同意这个方法签名合同,我们就可以“接口”。至于抽象类,我认为更多的是存根一些方法的基类,我需要填充细节。

你将在PHP中使用接口:

隐藏实现——建立一个对对象类的访问协议,改变底层实现,而不需要在所有使用过对象的地方进行重构 检查类型-例如确保参数具有特定类型$object instanceof MyInterface 在运行时强制参数检查 要在单个类中实现多个行为(构建复杂类型)

类Car实现EngineInterface, BodyInterface, steinginterface { 这样Car对象现在可以start(), stop() (EngineInterface)或goRight(),goLeft()(转向接口)

还有其他我现在想不起来的事情

第四点,这可能是你不能用抽象类解决的最明显的用例。

来自《Java思维》:

接口表示:“这是实现这个特定接口的所有类的样子。”因此,任何使用特定接口的代码都知道可以为该接口调用哪些方法,仅此而已。因此,接口用于在类之间建立“协议”。

我不记得PHP在这方面是否有所不同,但在Java中,您可以实现多个接口,但不能继承多个抽象类。我认为PHP也是这样工作的。

在PHP中,您可以通过用逗号分隔多个接口来应用它们(我认为,我不认为这是一个干净的解决方案)。

至于多个抽象类,你可以有多个相互扩展的抽象(同样,我不完全确定,但我想我以前在某个地方见过)。唯一不能扩展的是final类。