【问题标题】:Doesn't Java Generics upper bound rule breaks Liskov substitution? [duplicate]Java 泛型上限规则不会破坏 Liskov 替换吗? [复制]
【发布时间】:2021-12-22 18:58:30
【问题描述】:

我正在阅读有关 Java 泛型的内容,但以下部分似乎有问题:

public class Farm {
  private List<Animal> animals;

  public void addAnimals(Collection<Animal> newAnimals) {
    animals.addAll(newAnimals);
  }
}

farm.addAnimals(cats); // Compilation error
farm.addAnimals(dogs); // Compilation error

Cat 和 Dog 是 Animal 的子类。

为了使其工作,需要定义一个带有上限的通配符类型:

public void addAnimals(Collection<? extends Animal> newAnimals)

我不应该可以互换使用子类和超类而不需要根据 Liskov 替换的定义设置上限吗:

可替换性是面向对象编程中的一个原则,它规定对象(例如类)和子对象(例如扩展第一个类的类)必须在不破坏程序的情况下可互换。

【问题讨论】:

  • 泛型不是协变的。因此,Collection&lt;Cat&gt; 不是Collection&lt;Animal&gt;。这不会破坏 LSP,因为 LSP 不关心泛型。我们使用the PECS mnoemonic
  • List&lt;Dog&gt;List&lt;Cat&gt;Collection&lt;Dog&gt;Collection&lt;Cat&gt; 等不是Collection&lt;Animal&gt; 的子类。
  • 如果不清楚,请注意我们替换的类型不是Cats、Dogs 和Animals,而是collections 那些东西。
  • @Sweeper 非常有意义,谢谢。我会研究 PECS。
  • 嗯,来自重复链接的accepted and most upvoted answer 很好地解释了为什么编译器不允许这样的事情是一件好事。

标签: java generics solid-principles liskov-substitution-principle


【解决方案1】:

只有猫的集合不是任何动物集合的子类。

这和编译错误是好事。否则,您可以声明仅包含猫的集合,并将狗放入其中。麻烦会接踵而至。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-04-27
    • 2014-05-04
    • 2019-10-13
    • 1970-01-01
    • 2010-12-03
    • 1970-01-01
    • 1970-01-01
    • 2016-08-20
    相关资源
    最近更新 更多