任何简单的方法来解释为什么我不能做List<Animal> animals = new ArrayList<Dog>()?
2022-09-02 00:00:49
我知道为什么人们不应该这样做。但是有没有办法向外行解释为什么这是不可能的。你可以很容易地向外行解释这一点:。狗是一种动物,但狗的清单不是动物的清单。Animal animal = new Dog();
我知道为什么人们不应该这样做。但是有没有办法向外行解释为什么这是不可能的。你可以很容易地向外行解释这一点:。狗是一种动物,但狗的清单不是动物的清单。Animal animal = new Dog();
想象一下,你创建了一个狗列表。然后,将其声明为List<Animal>并将其交给同事。他不无理地相信他可以把一只猫放进去。
然后他把它还给你,你现在有一份狗的清单,中间有一只猫。混乱接踵而至。
请务必注意,由于列表的可变性,存在此限制。例如,在Scala中,您可以声明狗列表是动物列表。这是因为 Scala 列表(默认情况下)是不可变的,因此将 Cat 添加到 Dog 列表中将为您提供新的动物列表。
您正在寻找的答案与称为协方差和逆方差的概念有关。某些语言支持这些(例如,.NET 4 添加了支持),但一些基本问题通过如下代码演示:
List<Animal> animals = new List<Dog>();
animals.Add(myDog); // works fine - this is a list of Dogs
animals.Add(myCat); // would compile fine if this were allowed, but would crash!
由于 Cat 源自动物,因此编译时检查会建议将其添加到 List 中。但是,在运行时,您无法将猫添加到狗列表中!
因此,尽管这在直觉上看起来很简单,但这些问题实际上非常复杂。
这里有一个关于.NET 4中协/逆变的MSDN概述:http://msdn.microsoft.com/en-us/library/dd799517(VS.100).aspx - 它也适用于java,尽管我不知道Java的支持是什么样的。