请解释一下什么时候我应该使用PHP接口,什么时候我应该使用抽象类?

我如何能改变我的抽象类在一个接口?


当前回答

抽象类和接口的区别:

抽象类

抽象类可以提供一些功能,而将其余的功能留给派生类。

派生类可以重写基类中定义的具体函数,也可以不重写。 从抽象类扩展而来的子类在逻辑上应该是相关的。

接口

接口不能包含任何功能。它只包含方法的定义。

派生类必须为接口中定义的所有方法提供代码。 完全不同且不相关的类可以使用接口在逻辑上分组在一起。

其他回答

最佳实践是使用接口来指定契约,并将抽象类作为契约的一个实现。该抽象类可以填充大量样板文件,因此您可以通过重写需要或想要的内容来创建实现,而不必强制使用特定的实现。

主要的区别是抽象类可以包含默认实现,而接口不能。

接口是没有任何实现的行为契约。

当您希望强制在您的系统中工作的开发人员(包括您自己)在他们将要构建的类上实现一组方法时,请使用接口。

当你想强迫在你的系统中工作的开发人员(包括你自己)实现一组方法,并且你想提供一些基本方法来帮助他们开发他们的子类时,使用抽象类。

另一件需要记住的事情是客户端类只能扩展一个抽象类,而它们可以实现多个接口。因此,如果您在抽象类中定义行为契约,这意味着每个子类可能只符合一个契约。有时这是一件好事,当你想强迫你的用户程序员沿着特定的路径。其他时候就不好了。想象一下,如果PHP的Countable和Iterator接口是抽象类而不是接口。

当您不确定该走哪条路时(如下面的cletus所述),一种常见的方法是创建一个接口,然后让抽象类实现该接口。

只是想添加一个例子,说明什么时候你可能需要使用这两种方法。我目前正在编写一个通用ERP解决方案中绑定到数据库模型的文件处理程序。

我有多个抽象类,处理标准的crud,也有一些特殊的功能,如转换和流的不同类别的文件。 文件访问接口定义了一组用于获取、存储和删除文件的通用方法。

通过这种方式,我可以为不同的文件拥有多个模板,以及一组具有明显区别的公共接口方法。接口对访问方法进行了正确的类比,而不是对基抽象类的类比。

接下来,当我将为不同的文件存储服务制作适配器时,这种实现将允许在完全不同的上下文中在其他地方使用接口。

再加上一些已经很好的答案:

Abstract classes let you provide some degree of implementation, interfaces are pure templates. An interface can only define functionality, it can never implement it. Any class that implements the interface commits to implementing all the methods it defines or it must be declared abstract. Interfaces can help to manage the fact that, like Java, PHP does not support multiple inheritance. A PHP class can only extend a single parent. However, you can make a class promise to implement as many interfaces as you want. type: for each interface it implements, the class takes on the corresponding type. Because any class can implement an interface (or more interfaces), interfaces effectively join types that are otherwise unrelated. a class can both extend a superclass and implement any number of interfaces: class SubClass extends ParentClass implements Interface1, Interface2 { // ... }

请解释什么时候我应该使用接口,什么时候我应该使用抽象类?

当您只需要提供一个模板而不需要任何实现时,请使用接口,并且您希望确保实现该接口的任何类(至少)与实现该接口的任何其他类具有相同的方法。

当您想要为其他对象(部分构建的类)创建基础时,请使用抽象类。扩展抽象类的类将使用一些定义/实现的属性或方法:

<?php
// interface
class X implements Y { } // this is saying that "X" agrees to speak language "Y" with your code.

// abstract class
class X extends Y { } // this is saying that "X" is going to complete the partial class "Y".
?>

我如何能改变我的抽象类在一个接口?

这是一个简化的例子。去掉任何实现细节。例如,将你的抽象类更改为:

abstract class ClassToBuildUpon {
    public function doSomething() {
          echo 'Did something.';
    }
}

to:

interface ClassToBuildUpon {
    public function doSomething();
}