组合优于继承
与方法调用不同,继承打破了封装
换句话说,一个子类依赖于其父类的实现细节来保
证其正确的功能。 父类的实现可能会从发布版本不断变化,如果是这样,子类可能会被破坏,即使它的
代码没有任何改变。 因此,一个子类必须与其超类一起更新而变化,除非父类的作者为了继承的目的而
专门设计它,并对应有文档的说明
只有在子类真的是父类的子类型的情况下,继承才是合适的。 换句话说,只有在两个类之间存在
「is-a」关系的情况下,B 类才能继承 A 类。 如果你试图让 B 类继承 A 类时,问自己这个问题:每个 B
都是 A 吗? 如果你不能明确的以“是的”来回答这个问题,那么 B 就不应该继承 A。如果答案是否定的,
那么 B 通常包含一个 A 的私有实例,并且暴露一个不同的 API :A 不是 B 的重要部分 ,只是其实现细
节
在决定使用继承来代替组合之前,你应该问自己最后一组问题。对于试图继承的类,它的 API 有没
有缺陷呢? 如果有,你是否愿意将这些缺陷传播到你的类的 API 中?继承传播父类的 API 中的任何缺
陷,而组合可以让你设计一个隐藏这些缺陷的新 API。
总之,继承是强大的,但它是有问题的,因为它违反封装。 只有在子类和父类之间存在真正的子类
型关系时才适用。 即使如此,如果子类与父类不在同一个包中,并且父类不是为继承而设计的,继承可
能会导致脆弱性。 为了避免这种脆弱性,使用组合和转发代替继承,特别是如果存在一个合适的接口来
实现包装类。 包装类不仅比子类更健壮,而且更强大。