我们可以使用简单的继承或接口而不是抽象.
为什么我们需要在PHP中使用抽象?我们如何使用抽象隐藏基本功能?我很困惑使用抽象和接口和继承.哪里用哪个?
请帮助理解我.
解决方法:
我认为首先澄清术语是非常重要的,以便更精细地回答这个问题.
>继承
>继承实际上广泛应用于许多面向对象的编程原则和概念.它只需要从另一个繁殖出来的东西.因此,无论您是实现接口还是扩展类,您仍然使用一种继承形式.它们不是相互排斥的概念.
>界面
>尝试想象一个像合同那样的界面.合同本身只是一份文件,通常是两方或多方之间的文件,规定了他们关系的规则.接口,特别是在OOP和PHP的上下文中,不提供实现.它们只提供实现类必须实现的必需公共方法.接口也无法自行实例化.
>抽象类
>抽象类类似于接口,因为它不能单独实例化,但不一定强制扩展类的合同.由于它是一个实际的类,而不仅仅是一个接口,它还允许实现.如果在抽象类中将方法声明为抽象,则此实现可以由抽象类本身提供,或者由扩展类提供.它还允许实现属性和私有/受保护方法,因为这里的继承就像一个基类而不仅仅是一个需求.
所以回答这个问题,“为什么我们在PHP中有抽象类”,因为它很有用.您可能会首先将这些视为棘手的想法,但它们实际上可以协同工作以提供联合实用程序.
例
考虑到有时候接口不足以创建有用的实现.接口只能强制存在方法,并且其签名与实现的接口兼容.例如,可能存在您希望提供接口的默认实现的情况.
interface Device {
public function input(Stream $in);
public function output(): Stream;
}
abstract class DefaultDevice implements Device {
protected $buffer = "";
public function input(Stream $in) {
$this->buffer .= $in->read(1024);
$this->process();
}
abstract protected function process();
}
所以现在任何扩展DefaultDevice的类都可以选择覆盖输入方法的实现.即使接口不需要它,它也必须实现一个处理方法.这意味着实现Device接口的其他类可以向后兼容,这仍然是一个实现细节.
进一步的例子
将实现与规范分开通常是编写良好的软件的关键属性.
作为一个很好的例子,看一下Device接口本身.我们依靠输入方法接受Stream类型和输出方法来返回Stream类型.由于Stream本身实际上可以是一个接口,这意味着任何实现Stream的类型都是可以接受的.所以我可以创建自己的类并实现Stream接口,而不会破坏此代码.
class CustomStream implements Stream {
public function read($bytes = 1024) {
/* implementation */
}
public function write($data) {
/* implementation */
}
}
$device->input(new CustomStream); // this will not throw an error