【问题标题】:Java Inheritance. Parent has list of parent, child must have list of childs. How?Java 继承。父母有父母的名单,孩子必须有孩子的名单。如何?
【发布时间】:2019-09-05 15:09:04
【问题描述】:

我正在努力实现下一个:

家长:

public class Animal {
    private List<Animal> relatives;

    public List<Animal> getRelatives() {
        return relatives;
    }

    public void setRelatives(List<Animal> relatives) {
        this.relatives = relatives;
    }
}

孩子:

public class Dog extends Animal {
    private List<Dog> relatives;

    public List<Dog> getRelatives() {
        return relatives;
    }

    public void setRelatives(List<Dog> relatives) {
       this.relatives = relatives;
    }
}

但由于某种原因,我收到方法冲突的错误。这甚至可以通过继承而不使用泛型类型吗?

【问题讨论】:

  • 这种设计违反了里氏替换原则。 Animal.getRelatives() 应该返回一个List&lt;Animal&gt;,所以根据 Liskov 替换原则,dog.getRelatives().add(new Cat()) 一定可以。

标签: java inheritance


【解决方案1】:

您实际上不需要覆盖/复制子类中的任何内容。

class Animal<Relative extends Animal<?>> {
  private List<? extends Relative> relatives;

  public List<? extends Relative> getRelatives() {
    return relatives;
  }

  public void setRelatives(List<? extends Relative> relatives) {
    this.relatives = relatives;
  }
}

class Dog extends Animal<Dog> {}

【讨论】:

  • 为什么是&lt;? extends Relative&gt;,而不仅仅是&lt;Relative&gt;
  • class Dog extends Animal&lt;String&gt; 似乎合法
  • class Animal&lt;R extends Animal&gt; { private List&lt;R&gt; relatives; ?
  • 明天在我的工作上试试这个。 Relative 是一个偶然的 java 类,还是作为 T 起作用?
  • @AndyTurner 允许将List&lt;DomesticDog&gt; 传递给setRelativesDomesticDog 扩展Dog
【解决方案2】:

您可以在父类中使用泛型并持有relatives。此外,您应该注意持有意外修改:

public class Animal<T extends Animal<?>> {

    private final List<T> relatives = new ArrayList<>();

    public final List<T> getRelatives() {
        return relatives.isEmpty() ? Collections.emptyList() : Collections.unmodifiableList(relatives);
    }

    public final void addRelative(T relative) {
        Objects.requireNonNull(relative);
        relatives.add(relative);
    }
}

public class Dog extends Animal<Dog> {

    // just for test
    public List<Dog> getRelativesDogs() {
        return super.getRelatives();
    }

    // just for test
    public void addRelativeDog(Dog dog) {
        super.addRelative(dog);
    }

}

【讨论】:

  • relatives.add(relative) 不会编译。
  • 我不确定T extends Animal&lt;?&gt;是否正确,因为你可以写class Dog extends Animal&lt;Cat&gt; {}
  • 我在想class Animal&lt;Parent extends Animal, Relative extends Parent&gt;,它会拒绝像Dog extends Animal&lt;Dog, Cat&gt;这样的东西,但我不确定它是否总是可以的。
  • @AndrewTobilko 我认为这不是应该关心的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-18
相关资源
最近更新 更多