繁体   English   中英

抽象类的目的是什么?

[英]What is the purpose of abstract classes?

我试图在PHP中学习OOP,我对接口和抽象类有一些困惑。 它们都不包含任何实现,只包含定义,并且应该通过它们的子类来实现。 抽象类的哪一部分明确区别于接口? 另外,由于它们有明显的相似性,我应该根据什么原因决定使用一个而不是另一个?

可以创建包含具体成员的抽象类,例如方法或属性。 您仍然无法直接实例化抽象类,但任何实例化的子类都可以从抽象类中定义的已实现成员中受益。

相比之下,接口从不包含任何实现逻辑。 它由每个实现类提供,以提供接口中定义的所有成员的实现。

在我如何查看其区别方面,一个子类的抽象的是,一类型的。 例如, DogAnimal 我将界面视为一种关系。 例如, ICanDisplayImages告诉我实现类可以显示图像,但不会告诉我类实际代表什么。

abstract类在自身和子类之间形成一个is-a关系,而一个interface创建一个follow-a关系。 因此,抽象类比接口更具体,它们也可能包含具体实现(例如模板方法 ),而接口定义实现类必须遵循的契约方法集。 这是一个更高级别的抽象,因为实现类不一定是抽象类。 用它来标准化你的API。

相关问题: https//stackoverflow.com/search?q = abstract + vssinterface

它们都不包含任何实现..

抽象类可以实现全部或部分方法。 但主要的理念是扩展现有的抽象类,在子类中添加新方法(扩展基本功能)。

在子类中,您只能扩展一个类(抽象类)。 抽象类定义必须实现的功能,或者只是通过子类中的其他方法扩展。

接口用于定义类行为。 你可以实现多个接口(并说我的子类必须这样做,这个和这个thigs!),但是你只能扩展一个抽象类。

除了在其他答案中描述的OOP哲学之外,我认为抽象类的主要用途是一种骨架。

当您设计应用程序或与团队合作时,它非常有用,因为您有一个基本代码可以使用并扩展它接近界面但具有更高级的工作流程。

抽象类和接口之间的主要区别在于接口定义了常见行为,其中抽象类是继承的基础类。 换句话说,抽象类定义了子类可能共享的一些核心方法和属性集。 考虑一个定义许可证的类。 所有许可证都具有某种类型的ID号,并颁发给某个人或组。 许可证类可以通过驱动程序许可证类,自行车许可证类和狩猎许可证类扩展,等等。 将许可类抽象化的主要原因是它定义了许可的抽象概念。 没有许可证这样的东西,所以通过声明类抽象,它不能被实例化。
另一方面,接口根本不定义对象。 它定义了方法签名。 任何实现接口的非抽象类都必须为接口中的所有方法提供实现。 这里的优点是该方法提供跨不同类型对象的公共接口,例如compareTo()在与Strings或任何其他对象一起使用时看起来相同。

如果方法未定义为抽象,则抽象类可以包含方法实现。 如果该方法被定义为抽象,则它不包含实现,但它需要由其继承者实现。 抽象类不能实例化,而只是继承自,以便继承者允许它使用其行为。

接口只定义方法签名,从中继承的任何类都必须实现接口中包含的所有方法。

通常,接口用于定义合同,因此您可以进行类型检查。 还有一种称为“对接口编程”的编程风格,这是一个好主意。 请参阅依赖性倒置原则

A.高级模块不应该依赖于低级模块。 两者都应该取决于抽象。

B.抽象不应该依赖于细节。 细节应该取决于抽象。“

因此,如果您定义函数和方法,而不是对类进行类型提示 ,则只需提示接口。

这是一个例子。 假设您为输入流和输出流定义接口,如下所示:

interface OutputStream{
  write($string); // Writes a string to the output.
  close(); // Closes the output stream.
}

interface InputStream{
  read($length); // Reads at most $length characters.
  eof(); // TRUE, if the input stream is empty.
}

您现在可以创建copy功能或方法,将流的完整输出复制到输入,而不需要任何输出:

// 50 is just chosen randomly.
function copy(InputStream $input, OutputStream $output){
  while(!$input->eof()){
    $output->write($input->read(50));}}

恭喜,您的copy实现现在适用于输入和输出流的每个组合,甚至不实现一个。

另一方面,抽象类可用于实现通用功能,而无需实现完全功能的类。

再一次,一个例子。 比方说,你想拥有输出流。 你想要一个方法write($s) ,它将一个字符串写入输出,你想要一个方法writeLine($s) ,它将字符串和一个额外的换行符写入输出。 那么这是合适的:

abstract class AbstractOutputStream{
  public function writeLine($s){
    $this->write($s."\n");}}

具体的输出流现在可以从抽象输出流继承,实现只需write并免费获得writeLine

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM