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<Cat>
不是Collection<Animal>
。这不会破坏 LSP,因为 LSP 不关心泛型。我们使用the PECS mnoemonic。
List<Dog>
、List<Cat>
、Collection<Dog>
、Collection<Cat>
等不是Collection<Animal>
的子类。
如果不清楚,请注意我们替换的类型不是Cat
s、Dog
s 和Animal
s,而是collections 那些东西。
@Sweeper 非常有意义,谢谢。我会研究 PECS。
嗯,来自重复链接的accepted and most upvoted answer 很好地解释了为什么编译器不允许这样的事情是一件好事。
【参考方案1】:
只有猫的集合不是任何动物集合的子类。
这和编译错误是好事。否则,您可以声明仅包含猫的集合,并将狗放入其中。麻烦会接踵而至。
【讨论】:
以上是关于Java 泛型上限规则不会破坏 Liskov 替换吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章