shm*_*sel 7 java inheritance composition guava effective-java
有效的Java第3版,第18项:优先于继承的组合描述了使用继承向类添加行为的问题:
子类中脆弱性的一个相关原因是它们的超类可以在后续版本中获取新方法.假设程序依赖于其安全性,因为插入到某个集合中的所有元素都满足某些谓词.这可以通过继承集合并覆盖每个能够添加元素的方法来保证,以确保在添加元素之前满足谓词.这可以正常工作,直到在后续版本中将能够插入元素的新方法添加到超类中.一旦发生这种情况,仅通过调用新方法就可以添加"非法"元素,而新方法不会在子类中重写.
推荐的解决方案:
不要扩展现有类,而是为新类提供一个引用现有类实例的私有字段...新类中的每个实例方法都会在现有类的包含实例上调用相应的方法并返回结果.这称为转发,新类中的方法称为转发方法 ...向现有类添加新方法对新类没有影响...编写转发方法很繁琐,但你必须为每个接口只写一次可重用转发类,并为您提供转发类.例如,Guava为所有集合接口提供转发类.
我的问题是,风险是否仍然存在方法也可以添加到转发类,从而打破子类的不变量?像Guava这样的外部库如何在转发类时采用更新的方法而不会冒客户端的完整性?
默认的假设似乎是您是编写转发类的人,因此您可以控制是否向其中添加任何内容。无论如何,这是使用组合而不是继承的常见方法。
Guava 示例似乎引用了Forwarding Decorators,它们被明确设计为继承。但它们只是帮助者,使创建这些转发类变得更简单,而不必在接口中定义每个方法;它们明确不会阻止您将来添加任何可能需要覆盖的方法:
请记住,默认情况下,所有方法都直接转发到委托,因此覆盖
ForwardingMap.put不会改变ForwardingMap.putAll. 请小心重写每个必须更改其行为的方法,并确保您的装饰集合满足其契约。
所以,如果我理解正确的话,番石榴并不是一个很好的例子。
| 归档时间: |
|
| 查看次数: |
256 次 |
| 最近记录: |