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

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

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

有人告诉我,这与从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,可能只是抛出一个异常。

其他回答

我们看到抽象类和接口的相似之处在于它们提供了必须在子类中实现的抽象方法。但是,二者仍有以下差异:

1.接口可以包含抽象方法和常量,但不能包含具体方法和变量。 2.接口中的所有方法都必须在公共可见性中 范围。 3.一个类可以实现多个接口,同时它可以继承 只来自一个抽象类。

                                  interface                      abstract class
the code                     - abstract methods               - abstract methods
                             - constants                      - constants                  
                                                              - concrete methods
                                                              - concrete variables

access modifiers             
                             - public                         - public
                                                              - protected
                                                              - private
                                                                etc.
number of parents          The same class can implement
                           more than 1 interface              The child class can 
                                                              inherit only from 1 abstract class

希望这将有助于任何人理解!

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

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

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

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

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

接口不仅仅是为了确保开发人员实现特定的方法。其思想是,因为这些类保证有特定的方法,即使不知道类的实际类型,也可以使用这些方法。例子:

interface Readable {
  String read();
}

List<Readable> readables; // dunno what these actually are, but we know they have read();
for(Readable reader : readables)
  System.out.println(reader.read());

在许多情况下,提供基类是没有意义的,不管是不是抽象的,因为实现变化很大,除了一些方法之外没有任何共同之处。

动态类型语言有“鸭子类型”的概念,你不需要接口;您可以自由地假设对象具有您正在对其调用的方法。在静态类型语言中,对象有一些方法(在我的例子中是read()),但没有实现接口,这种方法可以解决这个问题。

在我看来,接口应该优于非函数抽象类。如果性能受到影响,我也不会感到惊讶,因为只实例化了一个对象,而不是解析两个对象,并将它们组合在一起(尽管,我不能确定,我不熟悉OOP PHP的内部工作原理)。

的确,与Java相比,接口没有那么有用/有意义。另一方面,PHP6将引入更多的类型提示,包括返回值的类型提示。这将为PHP接口增加一些价值。

interfaces定义了需要遵循的方法列表(想想API),而抽象类提供了一些基本/通用的功能,这些功能由子类细化以满足特定需求。