为什么更喜欢组合而不是继承?每种方法都有哪些权衡?什么时候应该选择继承而不是组合?
当前回答
这条规则完全是无稽之谈。为什么?
原因是,在任何情况下,都可以区分是使用组合还是继承。这取决于对一个问题的回答:“是什么?是什么?”或“有什么?”其他的东西“。
你不能“宁愿”把某样东西变成另一样东西或拥有另一样。严格的逻辑规则适用。
也没有“人为的例子”,因为在任何情况下都可以给出这个问题的答案。
如果你不能回答这个问题,还有其他问题。这包括类的责任重叠,这通常是错误使用接口的结果,较少是通过在不同类中重写相同的代码。
为了避免这种情况,我还建议为类使用与它们的职责完全相似的好名称。
其他回答
假设飞机只有两个部分:发动机和机翼。然后有两种设计飞机等级的方法。
Class Aircraft extends Engine{
var wings;
}
现在你的飞机可以从固定机翼开始并在飞行中将其改为旋转翼。它本质上是有翅膀的发动机。但如果我想改变呢发动机也在飞行?
基类Engine公开一个赋值函数以更改其财产,或我将飞机重新设计为:
Class Aircraft {
var wings;
var engine;
}
现在,我也可以随时更换发动机。
正如许多人所说的,我首先要检查是否存在“是”的关系。如果存在,我通常检查以下内容:
是否可以实例化基类。也就是说,基类是否可以是非抽象的。如果可以是非抽象的,我通常更喜欢写作
例如1。会计是员工。但我不会使用继承,因为Employee对象可以实例化。
例如2。书籍是SellingItem。SellingItem无法实例化-它是抽象概念。因此,我将使用遗传痤疮。SellingItem是一个抽象基类(或C#中的接口)
你觉得这种方法怎么样?
此外,我支持为什么要使用继承?
使用继承的主要原因不是作为组合的一种形式,而是为了让您可以获得多态行为。如果不需要多态性,那么可能不应该使用继承。
@马修。在https://softwareengineering.stackexchange.com/questions/12439/code-smell-inheritance-abuse/12448#comment303759_12448
继承的问题在于它可以用于两个正交的目的:接口(用于多态性)实现(用于代码重用)
参考
哪个班级设计更好?继承与聚合
你想强迫自己(或其他程序员)坚持什么,什么时候你想让自己(或另一个程序员)有更多的自由。有人认为,当你想强迫某人以某种方式处理/解决某个特定问题时,继承是有帮助的,这样他们就不会走错方向。
Is-a和Has-a是一个有用的经验法则。
将遏制视为一种关系。汽车“有”发动机,人“有”名字等等。
把继承看作是一种关系。汽车“是”车辆,人“是”哺乳动物等。
我不认为这种做法值得赞扬。我直接从史蒂夫·麦康奈尔(Steve McConnell)的《代码大全》第二版第6.3节中得到了答案。
另一个非常实用的原因是,倾向于组合而不是继承,这与域模型以及将其映射到关系数据库有关。将继承映射到SQL模型真的很难(你最终会遇到各种棘手的变通方法,比如创建不经常使用的列、使用视图等)。一些ORML试图处理这个问题,但它总是很快变得复杂。通过两个表之间的外键关系可以很容易地对组合进行建模,但继承要困难得多。
推荐文章
- 面向方面编程与面向对象编程
- super()失败,错误:TypeError "参数1必须是类型,而不是classobj"当父不继承对象
- 什么是ORM,它是如何工作的,我应该如何使用它?
- 我能在服务器端应用程序(PHP、Ruby、Python等)上读取URL的哈希部分吗?
- c++中类似于java的instanceof
- 多少个参数是太多?
- 在python中遍历对象属性
- 将类代码分离为头文件和cpp文件
- 在PHP中使用getter和setter而不是函数或简单的公共字段有什么优点?
- c++中的结构继承
- 基于原型的继承与基于类的继承
- “低耦合高内聚”是什么意思
- 你不应继承std::vector
- 对于不可变集合上的非突变“add”方法,最好的名称是什么?
- 如何从javascript子类调用父方法?