Answers:
从技术上讲,这些差异并不是真正重要,但是从概念上讲,它们是完全不同的事物,这导致了其他人提到的技术差异。
抽象超类的确切含义就是它,它是一种常见的类型,许多其他类型都共享这种类型,例如“猫和狗是动物”。
接口也正是它的外表,它是其他类可以与对象进行通信的接口。如果您想让猫走路,可以的,因为猫实现了CanWalk接口。蜥蜴也一样,尽管它们的行走方式非常不同。另一方面,Snake没有实现CanWalk,因此您不能告诉它走路。同时,蜥蜴和蛇(或者可能是更明确的子类-我不是专家)可能都剥皮了,因此实现了CanShed,而猫则无法做到。
但是它们仍然是动物,并且具有一些共同的属性,例如它们是活的还是死的。
这就是为什么接口上的所有方法都必须实现为公共的(或在C#中显式实现)的原因。在与对象接口的类中隐藏的接口的意义是什么?这就是为什么即使语言不支持多重继承,您也可以对一个对象具有多个接口的原因。
回到您的问题,当您以这种方式看待它时,几乎没有理由拥有一个完全抽象的超类。
在像C ++这样的语言中,它允许多重继承,并且没有接口,所有方法都抽象的抽象类可以用作接口。我使用C ++的工作不是很多,但是我猜想,当基类中有同名的方法时,多重继承会引起问题。
在PHP和C#之类的语言中,接口提供了一种实现类似的多态性的方法,尽管我不喜欢将其称为“继承”,因为在继承抽象类和实现接口之间存在概念上的差异。接口消除了冲突问题,因为它们本身不提供任何实现。
接口是与外界的契约,而抽象类可以提供实现,尽管如果用于“伪造”接口,则很可能不会。
主要的概念差异是,当一个类继承另一个类(是否抽象)时,存在“ is”关系,因此a Car
是a Vehicle
和Dog
is an Animal
。使用接口,对象要做的事情很重要。所以罐子Car
和Dog
罐子Move()
以及消费者都知道这是因为他们实施了Movable
,但是汽车绝对不是a Dog
或an Animal
。而且move的实现会有所不同(轮子与腿),但是使用代码并不在乎,也不在乎。接口都是关于消耗代码的,而不是实现。
要点是,如果您有使用自己选择的语言的接口,请将其用于存在的用途。如果不是这样(例如在C ++中),则可以使用纯抽象类来伪造它们。
Dog
和Cat
的。
抽象类可能具有受抽象保护的方法(以我正在使用的语言),在接口中,方法通常总是公共的。这种差异是否允许有用的利用,我不知道。
编辑我首先认为私有抽象方法没有用,但现在我回想起可以将其用于确保从不调用该方法。这样,您可以防止调用对象的副本构造函数。
我认为主要区别在于:在抽象类中-即使所有方法都是抽象的,它们仍然可以为实现它的类提供数据成员(实例变量)和一些代码(以私有方法或构造函数的形式),静态块;为子类做部分工作并帮助他们实施。
一个积极的副作用:代码在一个地方,所以一个地方可以进行更正。子类可以只调用父类方法,然后在父类动作足以满足其情况的情况下执行其他操作或不执行任何操作。超级类希望每个子类都做出此决定,因此已将其所有实现标记为抽象(有些可能也为空)
与问题无关:但是具有接口意味着一个类可以实现两个不同的合同。因此,与抽象超类相比,这是接口的优点