繁体   English   中英

抽象类,接口或抽象方法的用途是什么

[英]What is the use of an abstract class, interface or an abstract method

我对于为什么使用抽象类或接口来实现或扩展感到困惑。 接口不包含任何代码,抽象方法也不包含任何代码。 那为什么我们要使用它们。 为什么我们不直接创建方法并在类中定义它们,而是使用接口或抽象类。 它们不包含任何代码,我们需要在我们的类中对其进行扩展后再对其进行定义。 为什么我们不在自己的类中定义这些方法,而是扩展接口然后定义它们。 我发现此类问题在stackoverflow中已问过几次,但无法理解答案。 谁能用简单的方式解释一下

抽象和接口的力量来自于您可以分离职责并编写模块化代码的事实:您(或其他人)代码的一部分可能只关心您拥有Animal并提供了处理动物的设施,而无需知道他们如何移动或进食。 代码的不同部分可能只关心定义具体的动物,例如DogBird等等,并详细说明了它们如何实际实现其所有功能。

通过使具体类(狗,鸟等)扩展一个通用的抽象接口(动物),您可以在为抽象接口编写的库中使用现在和将来的任何具体类-无需要求图书馆作者更改图书馆以容纳新的动物,图书馆作者不需要知道如何具体实现功能。

例如,如果您有两个单一算法FeedBreakfastFeedDinner ,则需要成员函数Animal::gobble() ,那么在没有继承的情况下,您需要为每种动物实现每种算法-即,最终得到M * N量代码! 通过使用一个通用的抽象接口,您可以将其简化为M + N M算法和N具体类,并且双方都不需要知道对方-他们都需要知道接口。

抽象类背后的想法是,您可以定义一组相似类的某些通用功能,但将其他细节留给实现(扩展)类。 在某种程度上,它们类似于接口,不同之处在于您可以实际实现抽象类中的某些功能。

但是,有什么意义,我听到你问了吗? 嗯,尽管您也可以在一个具体的(非抽象的)基类中完成一次通用代码,但是您只需编写一次即可。 但是您也可能不希望其他程序员实例化基类,因此这才是抽象类真正强大的地方。

让我举一个例子来说明我的观点。 想象一下,您正在编写一个程序,对动物园中的所有动物进行分类。 动物可以分为某些类型,如鸟类,爬行动物,哺乳动物,昆虫,蜘蛛,鱼类等,然后分为其种类,如狗,猫,鹦鹉或袋鼠。 基类Animal可以为所有这些提供某些通用功能。 它可能具有一个称为eat()的函数,所有动物都以类似的方式执行该函数,因此该函数被写出以描述动物进食的过程。 它可能包含另一个函数walk(),但这是抽象的,因为不同的动物将以不同的方式实现它。 Animal类的所有子类都需要实现此方法。

这样做的主要好处是,您可以在代码中的某处调用以动物为参数的函数。 您知道可以在此参数上调用eat()和walk()函数,因为所有动物都可以进食和行走。 这被称为多态,是面向对象编程的重要特征。

希望对您有所帮助。 如果您仍然看不到抽象类的价值,请随时讨论或提出其他问题。

静态类型语言需要使用此方法来启用多态。 也就是说,您可以根据抽象基类编写代码。 然后,您可以“插入”任何子类作为扩展。 这称为Liskov替换原理 ,或打开/关闭原理 从技术上讲,这称为动态绑定 即,将在运行时根据子类选择要调用的方法。

对于动态类型的语言,情况则完全不同。 我不知道PHP是否是动态类型的(我怀疑是这样),但是例如在Ruby或Javascript中,您可以根据符合特定接口的任何对象进行编程。 就是说,如果您的代码期望一个对象具有一个称为Print的方法,则可以用其他任何一个也具有Print方法的对象代替,而无需派生一个通用的基类。 将在运行时查找该方法,这就是为什么将这些语言称为“ 动态 ”的原因。

希望这可以帮助!

要建立协议时,可以使用抽象类或接口。

听起来很简单,但这是一个非常强大的概念。 如果您被迫遵守规则,那么您将无法违反规则。 如果您不能违反规则,请遵守该协议。 因此,实现您的接口的所有类在本质上应该彼此兼容。 当然,人类中也有例外,他们可以通过创建代码来打破这些规则,甚至解释员在必须解析它们时也会哭泣,但这有点题外话:)

对于接口,假设您有一个名为“消息”的类。 这实现了名为SendMessage的接口,该接口具有Send的方法定义。

如果然后创建“消息”的两个子类。 一个可能是“电子邮件”,另一个可能是“ InstantMessage”。

现在它们都具有方法Send(),该方法在SendMessage接口中定义,并且为空。 现在,这使您可以不同地定义Send()方法的作用。 但是,由于我们知道类Email和InstantMessage使用接口SendMessage,因此我们知道它们都具有方法Send();。

因此,您可以调用Email.Send()和InstantMessage.Send(),但要做两件事。 接口定义了可用于多个对象的方法,但方法名称相同。

抽象类/接口主要是设计时的考虑因素。 通过将方法定义为抽象,因此也将类定义为抽象,我们确保可以肯定地通过派生类来实现这些方法。 如果他们不执行它们,它们也会变得抽象。

接口提供了将必须实现的方法分布到不同类别中的奢侈性,因此可以实现所需数量的接口。

抽象类保证不能实例化,这是因为是泛化。 例如,在游戏中,存在一个阶级玩家,但也存在一个阶级后卫和前锋。 类播放器是两个类的父类。 并不是创建一个对象球员的做法,因为团队需要一个特定的球员。

接口与多态有关。 每个类,根据其行为使用方法。

希望对您有帮助

暂无
暂无

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

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