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


当前回答

当你在两个类之间有一个is-a关系(例如狗是狗),你就去继承。

另一方面,当你在两个班级(学生有课程)或(老师学习课程)之间有一种或某种形容词关系时,你选择了作文。

其他回答

理解这一点的一个简单方法是,当您需要类的对象与其父类具有相同的接口时,应该使用继承,这样它就可以被视为父类的对象(上广播)。此外,派生类对象上的函数调用在代码中的任何地方都保持不变,但要调用的特定方法将在运行时确定(即,低级实现不同,高级接口保持不变)。

当您不需要新类具有相同的接口时,即您希望隐藏该类的用户不需要知道的类实现的某些方面时,应使用组合。因此,组合更多的是支持封装(即隐藏实现),而继承意味着支持抽象(即提供某种东西的简化表示,在这种情况下,相同的接口用于具有不同内部结构的一系列类型)。

尽管作文是首选,但我想强调继承的优点和作文的缺点。

继承优势:

它建立了逻辑“IS a”关系。如果汽车和卡车是两种类型的车辆(基类),则子类是一个基类。即汽车就是车辆卡车是一种车辆通过继承,您可以定义/修改/扩展功能基类不提供实现,子类必须重写完整方法(抽象)=>您可以实现合约基类提供默认实现,子类可以更改行为=>您可以重新定义合约子类通过调用super.methodName()作为第一条语句来向基类实现添加扩展=>您可以扩展合约基类定义了算法的结构,子类将覆盖算法的一部分=>您可以在不改变基类骨架的情况下实现Template_method

组成的缺点:

在继承中,子类可以直接调用基类方法,即使它由于IS A关系而没有实现基类方法。如果使用组合,则必须在容器类中添加方法以公开包含的类API

例如,如果汽车包含车辆,并且您必须获得汽车的价格(已在车辆中定义),您的代码将如下

class Vehicle{
     protected double getPrice(){
          // return price
     }
} 

class Car{
     Vehicle vehicle;
     protected double getPrice(){
          return vehicle.getPrice();
     }
} 

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

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

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

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

合成与继承是一个广泛的主题。对于什么更好,没有真正的答案,因为我认为这一切都取决于系统的设计。

通常,对象之间的关系类型为选择其中一个对象提供了更好的信息。

如果关系类型是“is-A”关系,则继承是更好的方法。否则关系类型为“HAS-A”关系,则组合将更接近。

这完全取决于实体关系。