如果'apple'是'fruit'的子类,那么List<apple>
是List<fruit>
的子类,这是正确的吗?
答案 0 :(得分:5)
没有! Mutable 容器就是这样不行 - 实际上是OOP的一个迷人方面。
进入List<fruit>
你可以插入香蕉 - 进入List<apple>
,你做不到;因此Liskov的原则被违反,证明你没有子类化。
不可变的容器确实按预期工作(协方差是艺术术语)。
有趣的是,我从未在印刷品中看到过这个引人入胜的法则(类似于 mutable 对象的世界,你不能说是一个Square IS-A矩形......但是在不可变对象的世界中,你可以!) - 我只是通过经验和观察得出它。我喜欢在这种背景下使用的学术性参考,如果有人能把它拉出来,BTW; - )
答案 1 :(得分:2)
没有。 List<apple>
和List<fruit>
无关。这两个类可能有完全不同的实现,没有办法将一个转换为另一个。例如,List<>
模板可以以某种方式专门用于apple
,其结构与常规List<T>
模板完全不同。
即使这些实现是兼容的,将List<apple>
视为List<fruit>
仍然是一个坏主意,因为人们会开始将各种水果放入该列表中应该包含苹果。另请参阅此entry in the C++ FAQ Lite,其中涉及苹果和香蕉......
答案 2 :(得分:1)
问题有点混乱,但我的第一个答案是不,至少在常规编程语言中。 a 继承 b 并不意味着 a 的任何变体也是 b 的相同变体的子类。
答案 3 :(得分:0)
在Java中,不,List<Apple>
不是List<Fruit>
的子类。它们都是List
类型。
这是一些证明这一事实的Java代码。
import java.util.LinkedList;
import java.util.List;
class Fruit { }
class Apple extends Fruit { }
public class Main {
public static void main(String[] args) {
Fruit fruit = new Fruit();
Apple apple = new Apple();
List<Fruit> fruitList = new LinkedList<Fruit>();
List<Apple> appleList = new LinkedList<Apple>();
System.out.println(fruit.getClass().getSuperclass());
System.out.println(apple.getClass().getSuperclass());
System.out.println(fruitList.getClass().getSuperclass());
System.out.println(appleList.getClass().getSuperclass());
}
}
输出:
class java.lang.Object
class Fruit
class java.util.AbstractSequentialList
class java.util.AbstractSequentialList
答案 4 :(得分:0)
取决于语言 - 在C#4.0中,您可以将IList<something>
转换为IList<object>
,但不能在C#3.0中执行此操作