Java 泛型上限规则不会破坏 Liskov 替换吗? [复制]

Posted

技术标签:

【中文标题】Java 泛型上限规则不会破坏 Liskov 替换吗? [复制]【英文标题】:Doesn't Java Generics upper bound rule breaks Liskov substitution? [duplicate] 【发布时间】: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 很好地解释了为什么编译器不允许这样的事情是一件好事。 【参考方案1】:

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

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

【讨论】:

以上是关于Java 泛型上限规则不会破坏 Liskov 替换吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

软件设计----LisKov替换原则(LSP)

Java 泛型通配符上限和通配符下限(正在整理)

怎么区别java泛型的上限和下限??

java 泛型的上限与下限

Java泛型理解

java泛型上限下限,通配符