我知道问题是之前讨论过 https://stackoverflow.com/questions/49002/prefer-composition-over-inheritance,但似乎总是假设继承至少有时比组合更可取。我想挑战这个假设,希望获得一些理解。
我的问题是这样的:Since你可以通过对象组合完成任何你可以通过经典继承完成的事情自从经典继承经常被滥用[1]自从对象组合使您可以灵活地更改委托对象运行时,为什么你会ever使用经典继承?
我可以理解为什么您会建议使用某些语言(例如 Java 和 C++)进行继承,因为这些语言不提供方便的委托语法。在这些语言中,只要没有明显错误,就可以通过使用继承来节省大量输入。但其他语言(例如 Objective C 和 Ruby)都提供经典继承and非常方便的委托语法。据我所知,Go 编程语言是唯一一种认为经典继承麻烦大于其价值并且仅支持代码重用委托的语言。
陈述我的问题的另一种方式是这样的:即使您知道经典继承对于实现某个模型来说并不是不正确,但是这个理由是否足以使用它而不是组合?
[1] 许多人使用经典继承来实现多态性,而不是让他们的类实现接口。继承的目的是代码重用,而不是多态。此外,有些人使用继承来模拟他们对“is-a”关系的直观理解这通常会出现问题 http://en.wikipedia.org/wiki/Circle-ellipse_problem.
Update
我只是想澄清一下当我谈论继承时我的确切含义:
我正在谈论类从部分或完全实现的基类继承的继承类型 http://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming). I am not谈论从纯粹的抽象基类继承,这与实现接口是一样的,我郑重声明,我并不反对这一点。
Update 2
我知道继承是C++实现多态性的唯一方法。在这种情况下,很明显为什么你必须使用它。所以我的问题仅限于 Java 或 Ruby 等语言,它们提供了实现多态性的不同方法(分别是接口和鸭子类型)。
[注意:这个问题最初被标记为与语言无关。基于此,这个答案的编写与语言无关,因此它讨论了在多种语言(例如 Smalltalk、C++ 和 Object Pascal)中使用的继承。此后它被重新标记为专门针对 Java。 Java 的不同之处在于定义class
and an interface
作为两个完全独立的事物。继承的目的是代码重用而不是多态性的想法从特定于 Java 的角度来看是合理的,但从与语言无关的角度来看显然是错误的。如果您只关心 Java,这可能不是最好的答案。]
继承的目的是代码重用,而不是多态。
这是你的根本错误。事实几乎恰恰相反。这primary(公共)继承的目的是对相关类之间的关系进行建模。多态性是其中很大一部分。
如果使用正确,继承并不是重用现有代码。相反,它是关于被使用by现有代码。也就是说,如果您有可以与现有基类一起使用的现有代码,那么当您从现有基类派生一个新类时,其他代码现在也可以自动与您的新派生类一起使用。
可以使用继承来重用代码,但是当/如果您这样做时,通常应该是private继承不是公共继承。如果您使用的语言很好地支持委派,那么您很可能没有太多理由使用私有继承。 OTOH,私有继承确实支持委托(通常)不支持的一些功能。特别是,尽管多态性在这种情况下绝对是次要问题,但它can仍然是一个问题——即,通过私有继承,您可以从基类开始almost你想要什么,并且(假设它允许)覆盖不太正确的部分。
对于委派,您唯一真正的选择是完全按原样使用现有类。如果它没有达到您想要的效果,您唯一真正的选择就是完全忽略该功能,并从头开始重新实现它。在某些情况下,这并不算什么损失,但在其他情况下,损失却相当可观。如果基类的其他部分使用多态函数,则私有继承允许您重写only多态函数,其他部分将使用您重写的函数。通过委派,您无法轻松插入新功能,因此现有基类的其他部分将使用您已覆盖的功能。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)