赞成合成而不是继承

a L*_*ner 53 java inheritance design-patterns

赞成合成而不是继承

是非常流行的短语.我读了几篇文章,最后每篇文章都说

当类之间存在纯粹的IS-A关系时使用继承.

本文的一个例子:

AppleFruit之间存在明显的IS-A关系,即Apple IS-A Fruit,但作者还将其显示为Apple HAS-A Fruit(组合),以显示继承实现时的陷阱.

我在这里有些困惑,声明的含义是什么

当类之间存在纯粹的IS-A关系时使用继承.

使用组合而不是继承是否意味着即使存在纯粹的IS-A关系也总是尝试应用组合, 并且只为那些组合没有意义的情况留下继承?

JB *_*zet 74

当您使用继承来重用超类中的代码时,而不是覆盖方法并定义另一种多态行为,这通常表明您应该使用组合而不是继承.

java.util.Properties班是一个坏的使用继承的一个很好的例子.它不是使用 Hashtable来存储其属性,而是扩展 Hashtable,以便重用其方法并避免使用委托重新实现其中的一些方法.

  • 我赞成,因为这是一个不涉及汽车,动物或水果的真实例子.但是,如果[`java.util.Properties`](https://docs.oracle.com/javase/7/docs/api/java/util/Properties.html)扩展,那将是一个更强有力的论据.因此,HashTable`对设计产生了负面影响.我想到Liskov Substitution Principle,我不认为这是一个问题.理论上,由于性能/内存原因,能够更改存储(散列)机制可能是有用的,但这对于继承是不可能的,并且可能与组合有关. (7认同)
  • 非rethorical问题:编写一个基类是不可取的,如果是抽象的,那么它包含的方法对于所有子类都具有完全意义,而不是覆盖任何基类的方法?不是`Properties`扩展`Hashtable`案例是一个很好的继承错误使用的例子,因为`Properties`不应该关心整个`Hashtable`特定的逻辑,只需要一小部分,所以它不应该扩展了`Hashtable`,因为它_is_不是一个,它只是_uses_一个? (3认同)

Cha*_*dra 7

我认为这是面向对象设计中讨论最多的一点.正如文章中所建议的,组合总是优于继承.这并不意味着你永远不应该使用继承.你应该在哪里更有意义(哪些可以辩论).

使用组合有许多优点,其中几个是:

  • 您将完全控制您的实施.即,您只能暴露您想要公开的方法.
  • 只能在您的班级中进行修改,才能屏蔽超类中的任何变化.任何使用您的类的客户端类都不需要进行修改.
  • 允许您控制何时加载超类(延迟加载)

  • 我的问题是我不介意转向更多的组合,但是对于具有许多方法的类,在每个派生类中重复该样板可能会很痛苦。当然,大多数类应该只有几个方法,但在某些情况下(例如 GUI Window 基类),您会情不自禁地拥有很多方法。 (2认同)