简体   繁体   English

抽象类的目的是什么?

[英]What is the purpose of abstract classes?

I am trying to learn OOP in PHP, and I have some confusion about interfaces and abstract classes. 我试图在PHP中学习OOP,我对接口和抽象类有一些困惑。 They both contain no implementations, only definitions, and should be implemented through their sub-classes. 它们都不包含任何实现,只包含定义,并且应该通过它们的子类来实现。 What part of abstract classes clearly distinguishes them from interfaces? 抽象类的哪一部分明确区别于接口? Also, due to their apparent similarities, based on what reasons should I decide to use one over the other? 另外,由于它们有明显的相似性,我应该根据什么原因决定使用一个而不是另一个?

It is possible to create abstract classes that contain concrete members, such as methods or properties. 可以创建包含具体成员的抽象类,例如方法或属性。 You still can't instantiate the abstract class directly, but any instantiated sub-classes can benefit from implemented members defined in the abstract class. 您仍然无法直接实例化抽象类,但任何实例化的子类都可以从抽象类中定义的已实现成员中受益。

An interface, by comparison, never contains any implementation logic. 相比之下,接口从不包含任何实现逻辑。 It is down to each implementing class to provide the implementation of all members defined in the interface. 它由每个实现类提供,以提供接口中定义的所有成员的实现。

In terms of how I view the differences, a sub-class of an abstract is-a class of that type. 在我如何查看其区别方面,一个子类的抽象的是,一类型的。 eg Dog is an Animal . 例如, DogAnimal I see an interface as a does-a relationship. 我将界面视为一种关系。 eg ICanDisplayImages tells me that the implementing class can display images, but tells me nothing about what the class actually represents. 例如, ICanDisplayImages告诉我实现类可以显示图像,但不会告诉我类实际代表什么。

An abstract class forms an is-a relationship between itself and the subclass, while an interface creates a follows-a relationship. abstract类在自身和子类之间形成一个is-a关系,而一个interface创建一个follow-a关系。 As such, abstract classes are much more concrete than interfaces and they may also contain concrete implementations (eg Template methods ) while an interface defines a contractual set of methods an implementing class must follow. 因此,抽象类比接口更具体,它们也可能包含具体实现(例如模板方法 ),而接口定义实现类必须遵循的契约方法集。 This is a much higher level of abstraction as the implementing class must not necessarily be of the abstract class. 这是一个更高级别的抽象,因为实现类不一定是抽象类。 Use it to standardize your API. 用它来标准化你的API。

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

They both contain no implementations.. 它们都不包含任何实现..

Abstract class can implements all or only part of the methods. 抽象类可以实现全部或部分方法。 But the main philosophy - is extend existing abstract class by to add a new methods in child classes (that extend a basic functionality). 但主要的理念是扩展现有的抽象类,在子类中添加新方法(扩展基本功能)。

In a child class you can extend only one class (abstract class). 在子类中,您只能扩展一个类(抽象类)。 Abstract class define functionality that you must implement or just extends by other methods in child classes. 抽象类定义必须实现的功能,或者只是通过子类中的其他方法扩展。

Interfaces are use to define the class behaviors. 接口用于定义类行为。 You can implement more than one interface(and say my child-class must do this,this and this thigs!), but you can extend only one abstract class. 你可以实现多个接口(并说我的子类必须这样做,这个和这个thigs!),但是你只能扩展一个抽象类。

Beyond the OOP philosophy described in other answers, I think the major use of abstract class is kind of a skeleton. 除了在其他答案中描述的OOP哲学之外,我认为抽象类的主要用途是一种骨架。

It's usefull when you design an application, or work with a team, because you have a base code to work with and extends it's close to interface but with a more advanced workflow. 当您设计应用程序或与团队合作时,它非常有用,因为您有一个基本代码可以使用并扩展它接近界面但具有更高级的工作流程。

The main difference between an abstract class and an interface is that an interface defines common behaviors, where an abstract class is a foundation class for inheritance. 抽象类和接口之间的主要区别在于接口定义了常见行为,其中抽象类是继承的基础类。 In other words, an abstract class defines some core set of methods and properties that subclasses might share. 换句话说,抽象类定义了子类可能共享的一些核心方法和属性集。 Consider a class that defines a License. 考虑一个定义许可证的类。 All licenses have an id number of some type and are issued to some individual or group. 所有许可证都具有某种类型的ID号,并颁发给某个人或组。 A license class might be extended by a Driver's License class, a Bicycle License class, and Hunting License class, and so on. 许可证类可以通过驱动程序许可证类,自行车许可证类和狩猎许可证类扩展,等等。 The main reason one would make the License class abstract is because it defines an abstract idea of a license. 将许可类抽象化的主要原因是它定义了许可的抽象概念。 There is no such thing as a license, so by declaring the class abstract, it cannot be instantiated. 没有许可证这样的东西,所以通过声明类抽象,它不能被实例化。
An interface, on the other hand, does not define an object at all. 另一方面,接口根本不定义对象。 It defines method signatures. 它定义了方法签名。 Any non-abstract class that implements an interface must provide an implementation for all of the methods in the interface. 任何实现接口的非抽象类都必须为接口中的所有方法提供实现。 The advantage here is the method provides a common interface across different types of objects, eg compareTo() looks the same when used with Strings or any other object. 这里的优点是该方法提供跨不同类型对象的公共接口,例如compareTo()在与Strings或任何其他对象一起使用时看起来相同。

An abstract class can contain method implementations if the method is not defined as abstract. 如果方法未定义为抽象,则抽象类可以包含方法实现。 If the method is defined as abstract, it does not contain an implementation, but it needs to be implemented by its inheritors. 如果该方法被定义为抽象,则它不包含实现,但它需要由其继承者实现。 An abstract class cannot be instantiated, but only inherited from, for the inheritor to allow it to use its behaviors. 抽象类不能实例化,而只是继承自,以便继承者允许它使用其行为。

An interface only defines method signatures and any class inheriting from it must implement all methods contained in the interface. 接口只定义方法签名,从中继承的任何类都必须实现接口中包含的所有方法。

Usually interfaces are used to define contracts, so you get type checking. 通常,接口用于定义合同,因此您可以进行类型检查。 There is also a programming style called "programming against interfaces", which is a good idea. 还有一种称为“对接口编程”的编程风格,这是一个好主意。 See the Dependency Inversion Principle : 请参阅依赖性倒置原则

A. High-level modules should not depend on low-level modules. A.高级模块不应该依赖于低级模块。 Both should depend on abstractions. 两者都应该取决于抽象。

B. Abstractions should not depend upon details. B.抽象不应该依赖于细节。 Details should depend upon abstractions." 细节应该取决于抽象。“

So if you define functions and methods, instead of type hinting against classes, you just hint against interfaces. 因此,如果您定义函数和方法,而不是对类进行类型提示 ,则只需提示接口。

Here is an example. 这是一个例子。 Let's say, you define interfaces for input streams and and output streams as follows: 假设您为输入流和输出流定义接口,如下所示:

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.
}

You could now create copy function or method, which copies the complete output of a stream to an input, without having any of them: 您现在可以创建copy功能或方法,将流的完整输出复制到输入,而不需要任何输出:

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

Congratulations, your copy implementation now works for every combination of an input and output stream, without even implementing one. 恭喜,您的copy实现现在适用于输入和输出流的每个组合,甚至不实现一个。

Abstract classes, on the other hand, can be used to implement common functionality without having to implement a fully functional class. 另一方面,抽象类可用于实现通用功能,而无需实现完全功能的类。

Again, an example. 再一次,一个例子。 Let's say, you want to have output streams. 比方说,你想拥有输出流。 You want a method write($s) , which writes a string to the output, and you want a method writeLine($s) , which writes the string and an additional newline to the output. 你想要一个方法write($s) ,它将一个字符串写入输出,你想要一个方法writeLine($s) ,它将字符串和一个额外的换行符写入输出。 Then this would be appropriate: 那么这是合适的:

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

Concrete output streams now could inherit from the abstract output stream, implement just write and get writeLine for free! 具体的输出流现在可以从抽象输出流继承,实现只需write并免费获得writeLine

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

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