为什么更喜欢组合而不是继承?每种方法都有哪些权衡?什么时候应该选择继承而不是组合?
当前回答
将遏制视为一种关系。汽车“有”发动机,人“有”名字等等。
把继承看作是一种关系。汽车“是”车辆,人“是”哺乳动物等。
我不认为这种做法值得赞扬。我直接从史蒂夫·麦康奈尔(Steve McConnell)的《代码大全》第二版第6.3节中得到了答案。
其他回答
将遏制视为一种关系。汽车“有”发动机,人“有”名字等等。
把继承看作是一种关系。汽车“是”车辆,人“是”哺乳动物等。
我不认为这种做法值得赞扬。我直接从史蒂夫·麦康奈尔(Steve McConnell)的《代码大全》第二版第6.3节中得到了答案。
当您想要“复制”/公开基类的API时,可以使用继承。当您只想“复制”功能时,请使用委派。
其中的一个例子是:您想要从列表中创建堆栈。堆栈只有pop、push和peek。考虑到堆栈中不需要push_back、push_front、removeAt等功能,您不应该使用继承。
假设飞机只有两个部分:发动机和机翼。然后有两种设计飞机等级的方法。
Class Aircraft extends Engine{
var wings;
}
现在你的飞机可以从固定机翼开始并在飞行中将其改为旋转翼。它本质上是有翅膀的发动机。但如果我想改变呢发动机也在飞行?
基类Engine公开一个赋值函数以更改其财产,或我将飞机重新设计为:
Class Aircraft {
var wings;
var engine;
}
现在,我也可以随时更换发动机。
在可以枚举不变量的情况下,子类型更合适,功能更强大,否则使用函数组合实现可扩展性。
尽管作文是首选,但我想强调继承的优点和作文的缺点。
继承优势:
它建立了逻辑“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();
}
}