《Effective Java第三版》中的第18条建议:优先使用组合而非继承,描述了在使用继承为类添加行为时可能会遇到的问题:
继承的一个相关问题是,超类可能会在后续版本中增加新的方法,导致子类变得脆弱。比如程序依赖于元素插入某个集合时满足某个谓词以确保安全性。可以通过子类化该集合并重写每个能够添加元素的方法来保证满足谓词的条件再添加元素。这样做很好用,直到在超类的后续版本中添加了能够插入元素的新方法。一旦出现这种情况,就可以通过调用新方法(该方法未在子类中重写)来添加“非法”元素。
推荐的解决方案是:不要扩展现有的类,而是给你的新类一个私有字段,引用一个现有类的实例...新类中的每个实例方法都调用包含的现有类实例上对应的方法,并返回结果。这被称为转发,新类中的方法称为转发方法... 在现有类中添加新方法将不会影响新类...编写转发方法很繁琐,但针对每个接口只需编写可重用的转发类一次,而且已经可以为你提供转发类。例如,Guava为所有集合接口提供了转发类。
我的问题是:在转发类中也可能添加新方法,这样不会破坏子类的不变式吗?像Guava这样的外部库如何在转发类中加入新方法而不危及其客户端的完整性?
继承的一个相关问题是,超类可能会在后续版本中增加新的方法,导致子类变得脆弱。比如程序依赖于元素插入某个集合时满足某个谓词以确保安全性。可以通过子类化该集合并重写每个能够添加元素的方法来保证满足谓词的条件再添加元素。这样做很好用,直到在超类的后续版本中添加了能够插入元素的新方法。一旦出现这种情况,就可以通过调用新方法(该方法未在子类中重写)来添加“非法”元素。
推荐的解决方案是:不要扩展现有的类,而是给你的新类一个私有字段,引用一个现有类的实例...新类中的每个实例方法都调用包含的现有类实例上对应的方法,并返回结果。这被称为转发,新类中的方法称为转发方法... 在现有类中添加新方法将不会影响新类...编写转发方法很繁琐,但针对每个接口只需编写可重用的转发类一次,而且已经可以为你提供转发类。例如,Guava为所有集合接口提供了转发类。
我的问题是:在转发类中也可能添加新方法,这样不会破坏子类的不变式吗?像Guava这样的外部库如何在转发类中加入新方法而不危及其客户端的完整性?
ArrayList
添加一个方法有什么不同吗? - shmosel