众所周知,(类)继承和子类型(有时称为接口继承)是不同的:继承是共享代码的机制,而子类型是允许在需要超类型对象的情况下替换子类型对象的关系,这是一种多态。
我在几个地方读到,有一种将两者混为一谈的编程语言机制是一件坏事。然而,许多OO语言就是这样做的(Java就是主要的例子)。我觉得这是有道理的:毕竟,如果我们有“A的B亚型”的亚型关系,那麽B类的物体便会与A类的物体有相同的行为,那麽,为何不一石二鸟,让B继承A的行为呢?
那为什么这是件坏事?我感兴趣的是一些例子,以及更一般的/理论上的理由。
发布于 2015-04-18 19:13:51
我以前从未听说过这种确切的说法,但从您的描述方式来看,它听起来与我熟悉的两个咒语密切相关:“偏好组合而不是继承”和“接口与实现分离”。
你似乎在使用的子类型的定义(我不怀疑它是否正确)是,如果A是B的一个子类型,这意味着A和B有相同的公共接口--可能还有一些额外的东西--这个接口对A履行了与B相同的契约。查找"Liskov替换原则“来获得更多信息。
这与说A共享B的一些代码有很大不同。有许多方法可以让类共享彼此的代码,而且(在大多数OOP语言中),最简单和最安全的方法之一是A有一个B类型的私有成员变量。
从另一个具体的B类继承一个具体的A类的问题是,除了告诉编译器A共享B的接口之外,你实际上也强迫A使用B的代码,如果你觉得A将来应该使用与B不同的实现,那么就没有容易的方法来分离这些东西。因此,我们可以说,A和B是紧密耦合的。人们常说,继承是现代编程语言中最紧密的耦合形式之一。
如果您创建了一个抽象的class/interface/whatever-your-language-calls-it,并使A和B继承,那么编译器就会理解它们具有相同的接口,但是它们的实现永远保持解耦。您可能仍然有A在内部使用B的一个实例,但是您可以随时更改它,而不会破坏任何客户端代码。您甚至可以切换它,以便如果您愿意的话,可以使用A来实现B。
现在,就我个人而言,我不认为编程语言对“接口继承”和“实现继承”使用相同的继承机制是错误的,主要是因为它们都没有强迫您使用该机制将类紧密耦合。如果只需要“接口继承”,则可以从抽象类继承。如果只想要“实现继承”,可以使用组合。另外,编程语言拥有的特性/机制越少,正确学习和使用就越容易。但我认为,任何声称这是一个错误的人,都是在采纳我上面总结的论点,只是向前走了一步。
https://softwareengineering.stackexchange.com/questions/279529
复制相似问题