为什么更喜欢组合而不是继承?每种方法都有哪些权衡?什么时候应该选择继承而不是组合?


当前回答

简而言之,我同意“比起继承,我更喜欢成分”,但对我来说,这听起来常常像“比起可口可乐,我更爱土豆”。有继承的地方,也有合成的地方。你需要了解差异,然后这个问题就会消失。这对我来说真正的意义是“如果你要使用继承——再想想,你很可能需要复合”。

当你想吃的时候,你应该更喜欢土豆而不是可口可乐,当你想喝的时候,应该更喜欢可口可乐而不是土豆。

创建子类不仅仅意味着调用超类方法的便捷方式。当子类在结构上和功能上都是一个超级类时,您应该使用继承,因为它可以用作超级类,并且您将使用它。如果不是这样的话,那不是继承,而是其他东西。合成是指你的对象由另一个组成,或者与它们有某种关系。

所以对我来说,如果有人不知道自己是否需要继承或组成,真正的问题是他不知道自己是想喝酒还是想吃饭。多想想你的问题领域,更好地理解它。

其他回答

将遏制视为一种关系。汽车“有”发动机,人“有”名字等等。

把继承看作是一种关系。汽车“是”车辆,人“是”哺乳动物等。

我不认为这种做法值得赞扬。我直接从史蒂夫·麦康奈尔(Steve McConnell)的《代码大全》第二版第6.3节中得到了答案。

在Java或C#中,对象一旦实例化就不能更改其类型。

因此,如果您的对象需要显示为不同的对象或根据对象的状态或条件表现出不同的行为,那么请使用组合:参考状态和策略设计模式。

如果对象需要具有相同的类型,则使用继承或实现接口。

继承是非常诱人的,尤其是来自程序领域的继承,它通常看起来很优雅。我的意思是,我需要做的就是将这一点功能添加到其他类中,对吗?嗯,问题之一是继承可能是最糟糕的耦合形式

基类通过以受保护成员的形式向子类公开实现细节来打破封装。这会使您的系统变得僵化和脆弱。然而,更悲惨的缺陷是新的子类带来了继承链的所有包袱和观点。

《继承是邪恶的:DataAnnotationsModelBinder的史诗般的失败》一文在C#中讲述了一个这样的例子。它显示了继承在何时应该使用组合以及如何重构组合。

这条规则完全是无稽之谈。为什么?

原因是,在任何情况下,都可以区分是使用组合还是继承。这取决于对一个问题的回答:“是什么?是什么?”或“有什么?”其他的东西“。

你不能“宁愿”把某样东西变成另一样东西或拥有另一样。严格的逻辑规则适用。

也没有“人为的例子”,因为在任何情况下都可以给出这个问题的答案。

如果你不能回答这个问题,还有其他问题。这包括类的责任重叠,这通常是错误使用接口的结果,较少是通过在不同类中重写相同的代码。

为了避免这种情况,我还建议为类使用与它们的职责完全相似的好名称。

继承是非常强大的,但你不能强迫它(参见:圆-椭圆问题)。如果你真的不能完全确定一个真正的“is-a”子类型关系,那么最好是组合。