具有两个列表的类的组合和转发方法

时间:2013-02-27 06:05:35

标签: java oop inheritance arraylist composition

我已阅读有效Java的第16项Prefer composition over inheritance?现在尝试将它应用于1年前编写的代码,当时我已经开始了解Java。

我正在试图塑造一种可以具有特征的动物,即游泳,肉食等,并获得不同类型的食物。

public class Animal {
    private final List<Trait> traits = new ArrayList<Trait>();
    private final List<Food> eatenFood = new ArrayList<Food>();

}

在第16项中,建议使用组合和转发可重复使用的方法:

public class ForwardingSet<E> implements Set<E> {
    private final Set<E> s;
    public ForwardingSet(Set<E> s) {this.s = s;}

    //implement all interface methods
    public void clear() {s.clear();}

    //and so on
}

public class InstrumentedSet<E> extends ForwardingSet<E> {
   //counter for how many elements have been added since set was created
}

我可以实现ForwardingList<E>,但我不确定如何将它应用于Animal类两次。现在Animal我有traits以及eatenFood等多种方法。这对我来说似乎很尴尬。

public boolean addTrait (Trait trait) {
    return traits.add(trait);
}

public boolean removeTrait (Trait trait) {
    return traits.remove(trait);
}
  1. 您如何重新设计Animal课程?

  2. 我应该保持原样还是尝试申请ForwardingList

1 个答案:

答案 0 :(得分:1)

没有理由要为此问题专门设置列表。你已经在这里使用了Composition,它几乎就是我对课程的期望。

组合基本上是创建一个具有一个(或通常更多)成员的类。转发实际上是让你的方法只是调用它所拥有的一个对象来处理它。这正是您已经在做的事情。

无论如何,你提到的方法正是我期望的一个具有特征的类的方法。我期待类似的addFood / removeFood食物方法。如果他们出错,他们就会出现几乎每个人都做错的确切错误。

IIRC(我的有效Java副本正在发挥作用):ForwardingSet的存在仅仅是因为你无法安全地扩展一个没有明确设计为扩展的类。如果没有记录自用模式等,则无法合理地将调用委托给超级方法,因为您不知道addAll可能会或可能不会为默认实现重复调用add。但是,您可以安全地委派调用,因为您委派的对象永远不会调用包装器对象。这绝对不适用于此;您已经将呼叫委托给列表了。