抽象类的目的是什么?
我正在尝试用 PHP 学习 OOP,但我对接口和抽象类有一些困惑。它们都不包含任何实现,只包含定义,并且应该通过它们的子类来实现。抽象类的哪一部分将它们与接口明确区分开来?另外,由于它们明显相似,基于什么原因我应该决定使用其中一种而不是另一种?
I am trying to learn OOP in PHP, and I have some confusion about interfaces and abstract classes. 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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
可以创建包含具体成员(例如方法或属性)的抽象类。您仍然无法直接实例化抽象类,但任何实例化的子类都可以从抽象类中定义的实现成员中受益。
相比之下,接口从不包含任何实现逻辑。每个实现类负责提供接口中定义的所有成员的实现。
就我如何看待差异而言,抽象的子类是该类型的类。例如,
Dog
是一种Animal
。我将接口视为一种做关系。例如,ICanDisplayImages
告诉我实现类可以显示图像,但没有告诉我该类实际代表什么。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. e.g.
Dog
is anAnimal
. I see an interface as a does-a relationship. e.g.ICanDisplayImages
tells me that the implementing class can display images, but tells me nothing about what the class actually represents.一个
abstract
类形成一个自身与子类之间的is-a关系,而接口
创建follows-a关系。因此,抽象类比接口更具体,它们也可能包含具体的实现(例如模板方法 )而接口定义了实现类必须遵循的一组契约方法。这是更高层次的抽象,因为实现类不一定是抽象类。用它来标准化您的 API。相关问题:https://stackoverflow.com/search?q=abstract+vs+interface
An
abstract
class forms an is-a relationship between itself and the subclass, while aninterface
creates a follows-a relationship. As such, abstract classes are much more concrete than interfaces and they may also contain concrete implementations (e.g. 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.Related questions: https://stackoverflow.com/search?q=abstract+vs+interface
除了其他答案中描述的 OOP 哲学之外,我认为抽象类的主要用途是一种骨架。
当您设计应用程序或与团队合作时,它非常有用,因为您有一个可以使用的基本代码,并可以扩展它以接近界面,但具有更高级的工作流程。
Beyond the OOP philosophy described in other answers, I think the major use of abstract class is kind of a skeleton.
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.
抽象类可以实现全部或仅部分方法。但主要理念是通过在子类中添加新方法(扩展基本功能)来扩展现有的抽象类。
在子类中,您只能扩展一个类(抽象类)。抽象类定义您必须实现或仅通过子类中的其他方法扩展的功能。
接口用于定义类行为。您可以实现多个接口(并且说我的子类必须执行此操作,此操作和此操作!),但您只能扩展一个抽象类。
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.
抽象类和接口之间的主要区别在于接口定义了常见的行为,而抽象类是继承的基础类。换句话说,抽象类定义了子类可能共享的一些核心方法和属性集。考虑一个定义许可证的类。所有许可证都有某种类型的 ID 号,并颁发给某些个人或团体。许可证类别可以通过驾驶执照类别、自行车许可证类别和狩猎许可证类别等进行扩展。将 License 类抽象化的主要原因是它定义了许可证的抽象概念。没有许可证这样的东西,因此通过声明类抽象,它无法被实例化。
另一方面,接口根本不定义对象。它定义了方法签名。任何实现接口的非抽象类都必须提供接口中所有方法的实现。这里的优点是该方法提供了跨不同类型对象的通用接口,例如,compareTo() 在与字符串或任何其他对象一起使用时看起来相同。
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. 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, e.g. compareTo() looks the same when used with Strings or any other object.
如果方法未定义为抽象,则抽象类可以包含方法实现。如果该方法被定义为抽象方法,则它不包含实现,但需要由其继承者实现。抽象类不能被实例化,只能被继承,以便继承者允许它使用其行为。
接口仅定义方法签名,任何继承自该接口的类都必须实现该接口中包含的所有方法。
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.
通常,接口用于定义契约,因此您可以进行类型检查。还有一种编程风格称为“针对接口编程”,这是一个好主意。请参阅依赖倒置原则:
因此,如果您定义函数和方法,而不是 针对类进行提示,您只需针对接口进行提示。
下面是一个示例,您可以按如下方式定义输入流和输出流的接口:
您现在可以创建
copy
函数。或方法,它将流的完整输出复制到输入,而不包含任何输入:恭喜,您的
copy
实现现在适用于输入和输出的每个组合 再举另一方面,抽象类可以用来实现通用功能,而无需实现功能齐全的类。
一个例子,您想要一个方法。
write($s)
,它将字符串写入输出,并且您需要一个方法writeLine($s)
,它将字符串和附加换行符写入输出。那么这将是合适的:具体输出流现在可以从抽象输出流继承,仅实现
write
并免费获取writeLine
!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:
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:
You could now create
copy
function or method, which copies the complete output of a stream to an input, without having any of them:Congratulations, your
copy
implementation now works for every combination of an input and output stream, without even implementing one.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 methodwriteLine($s)
, which writes the string and an additional newline to the output. Then this would be appropriate:Concrete output streams now could inherit from the abstract output stream, implement just
write
and getwriteLine
for free!