在包的内部使用继承是非常安全的,在那里子类和超类的实现都处在同一个程序员的控制之下。对于专门为了继承而设计并且具有很好的文档说明的类来说(详见第19条),使用继承也是非常安全的。
然而,对普通的具体类进行跨越包边界的继承,则是非常危险的。
其原因主要是因为:
与方法调用不同的是,继承打破了封装性。子类依赖于其超类中特定功能的实现细节。如果超类中的实现改变,就有可能给子类的逻辑带来很大的危害。因而,子类必须要跟着其超类的更新而演变,除非超类是专门为了扩展而设计的,并且具有很好的文档说明。
既不扩展现有的类,而是在新的类中增加一个私有域,它引用现有类的一个实例。。这种设计被称为复合,因为现有的类变成了新类的一个组件。新类中的每个实例方法都可以调用被包含的现有类实例中对应得方法。这样得到的类将会非常稳固,它不依赖于现有类的实现细节。即使现有类添加了新的方法,也不会影响新的类。
eg:
public class A { private B b;//加入B对象的引用来替代继承 ..... .... }
如果想要在A中规范B中相应的接口,可采用装饰器模式的写法。
eg:
public class B implement InterfaceB{ .... } public class A extend B implement InterfaceB{ .... }
简而言之,继承的功能非常强大,但是也存在诸多的问题,因为它违反了封装的原则。只有当子类和超类之间确实存在类型关系时,使用继承才是恰当的。即便如此,如果子类和超类处在不同的包中,并且超类并不是为了继承而设计的,那么继承将会导致脆弱性,为了避免这种脆弱性,可以用复合和转发的机制(装饰复合类的方法)来代替继承,尤其是当存在适当的接口可以实现包装类的时候,包装类不仅比子类更加健壮,而且功能也更加强大。
。