2012-11-17 58 views
0

我刚刚在我的编程语言课上学到“逆变参数类型实际上是安全的,但它们没有被发现有用,因此在实际语言中不被支持。”即使他们不支持,我很困惑,为什么这样的例子中,我们分别给予仍然是,从理论上讲,“安全”:为什么这些逆变参数类型被认为是安全的?

class Animal { 
    ... 
    public bool compare(Panda) { ... } 
} 

class Panda extends Animal { 
    ... 
    public bool compare(Animal) { ... } 
} 

据我了解,与子类型的问题上来,当东西这样做会导致特异性的丧失。那么,如果我这样做呢? :

Panda p = new Panda(); 
Animal a = new Animal 
... 
p.compare(a); 

当我看着这个,看起来像熊猫可能(可能确实)有一些额外的领域,普通的动物不知道。因此,即使他们所有的动物特定数据成员都是相同的,熊猫也可以有其他不同的东西。如何将它与一个普通的动物相比较呢?它会只考虑动物的东西,而忽略其余的东西吗?

回答

2

在您的示例中,您不使用任何generic类型。你有Panda延伸Animal,这是一个inheritance的例子,并导致polymorphism这是或多或少你所描述的。检查链接。

要获得反转效果,您需要考虑一些通用类型。我将以.NET类型IComparer`1[T]为例。用C#语法(这我会用,而不是Java),我们表明,IComparer逆变T由定义写in

public interface IComparer<in T> 
{ 
    ... 
} 

假设我有一个返回IComparer`1[Animal](或IComaparer<Animal>的方法),如:

static IComparer<Animal> CreateAnimalComparer() 
{ 
    // code that returns something here 
} 

现在在C#中,这是法理上的说法:

IComparer<Panda> myPandaComparer = CreateAnimalComparer(); 

现在,这个是因为变相。请注意,类型IComparer<Animal>不是源自(或“扩展”)IComparer<Panda>类型。相反,Panda来自Animal,这导致IComparer<Xxxx>可以相互赋值(以相反的顺序,因此“逆变”(而不是“协方差”))。

声明Comparer<>逆变是有意义的原因是,如果你有一个比较器可以比较两个任意的动物,并返回一个有符号的数字来表明哪个更大,那么同一个比较器也可以取两个熊猫并比较那些。熊猫是动物。

所以关系

任何PandaAnimal

(从继承)导致关系

任何IComparer<Animal>IComparer<Panda>

(通过反转)。

对于协方差,相同的关系

任何Panda一个例子是一个Animal

导致

任何IEnumerable<Panda>被一个IEnumerable<Animal>

by covariance(IEnumerable<out T>)。

相关问题