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

标签 java oop inheritance arraylist composition

我已阅读《Effective 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类(class)。现在在Animal我有很多类似下面的方法 traits也适用于eatenFood 。这对我来说似乎很尴尬。

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

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

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

最佳答案

您没有理由想专门使用一个列表来解决这个问题。您已经在这里使用了“组合”,这几乎正是我对类(class)的期望。

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

无论如何,您提到的方法正是我所期望的具有 Trait 的类的方法。我期望类似的 addFood/removeFood 类型的食物方法。如果他们错了,那也是几乎每个人都犯过的错误。

IIRC(我的Effective Java 副本正在工作):ForwardingSet 的存在只是因为您无法安全地扩展未明确设计为扩展的类。如果未记录自使用模式等,则您无法合理地将调用委托(delegate)给 super 方法,因为您不知道 addAll 可能会也可能不会为默认实现重复调用 add 。但是,您可以安全地委托(delegate)调用,因为您委托(delegate)的对象永远不会调用包装器对象。这绝对不适用于这里;您已将调用委托(delegate)给该列表。

关于java - 具有两个列表的类的组合和转发方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15105295/

相关文章:

c++ - 禁止在派生类中使用默认构造函数,C++

java - 找到一个名为 ".git/.MERGE_MSG.swp"的交换文件

java - 在 Spring Boot 中使用 @EnableWebFluxSecurity 时出错

javascript - 如何使用 OO JavaScript 管理 GUI 交互?

C++继承与抽象函数实现

python - Python中的简单类继承

java - 2 个 Java 线程能否作为两个不同的 Kerberos 用户(在同一进程中)进行身份验证?

java - 使用java从以WE8ISO8859P1编码的Oracle数据库读取阿拉伯文本

java - 类和函数结构(Java)

java - 构造函数应该何时以及如何对实例变量施加限制?