那个答案中没有什么不鼓励扩展ArrayList;有一个语法问题.类扩展存在,所以我们可以重新使用代码.
根据请求编辑组合示例.
public class ThingContainer implements List { // Or Collection based on your needs.
List things;
public boolean add(Thing thing) { things.add(thing); }
public void clear() { things.clear(); }
public Iterator iterator() { things.iterator(); }
// Etc.,and create the list in the constructor
}
您不一定需要公开一个完整的列表界面,只是收集,或根本没有.尽管没有显示功能大大降低了一般的有用性.
在Groovy中,您可以使用@Delegate注释自动构建方法. Java可以使用Project Lombok的@Delegate注释来做同样的事情.我不知道龙目岛如何暴露界面,或者如果它.
我用glowcoder,在这种情况下,我没有看到任何扩展的根本错误 – 这真的是一个解决问题的问题.
编辑关于继承如何违反封装的细节
有关详细信息,请参阅Bloch的有效Java,第16项.
如果一个子类依赖于超类行为,并且超类的行为发生变化,则子类可能会中断.如果我们不控制超类,这可能是坏的.
这是一个具体的例子,从书中解除(对不起Josh!),伪代码,并大量释义(所有的错误都是我的).
class CountingHashSet extends HashSet {
private int count = 0;
boolean add(Object o) {
count++;
return super.add(o);
}
boolean addAll(Collection c) {
count += c.size();
return super.addAll(c);
}
int getCount() { return count; }
}
然后我们用它:
s = new CountingHashSet();
s.addAll(Arrays.asList("bar","baz","plugh");
它返回…三?不.六.为什么?
HashSet.addAll()在HashSet.add()上实现,但这是一个内部实现细节.我们的子类addAll()添加三个,调用super.addAll(),它调用add(),它也增加count.
我们可以删除子类的addAll(),但现在我们依赖于超类实现细节,这可能会改变.我们可以修改我们的addAll()来迭代并在每个元素上调用add(),但是现在我们正在重新实现超类行为,如果超类行为取决于对私有成员的访问,那么它们的目的就会失败,而且可能并不总是可能的.
或者一个超类可以实现一个新的方法,我们的子类不会,这意味着我们的类的用户可能无意中通过直接调用超类方法绕过预期的行为,所以我们必须跟踪超类API来确定什么时候,如果是子类应改变.