派生对象的模板是基类型模板的子类

时间:2009-06-29 04:43:12

标签: templates

如果'apple'是'fruit'的子类,那么List<apple>List<fruit>的子类,这是正确的吗?

5 个答案:

答案 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中执行此操作