为什么这些逆变论证类型被认为是安全的?

时间:2012-11-17 17:53:29

标签: contravariance

我刚刚在我的编程语言课程中学到了“逆变参数类型实际上是安全的,但它们并没有被发现有用,因此在实用语言中不受支持。”虽然它们不受支持,但我很困惑为什么我们这样的例子在理论上仍然是“安全的”:

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); 

当我看到这一点时,似乎熊猫可能(并且可能确实)有一些额外的领域,普通动物不会知道。因此,即使他们所有的动物特定数据成员相同,熊猫也可以拥有其他不同的东西。如何将它与普通动物进行比较呢?它会仅仅考虑动物的东西而忽略其余的东西吗?

1 个答案:

答案 0 :(得分: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<>逆变器有意义的原因是,如果你有一个可以比较两个任意动物的比较器,并返回一个表示哪个更大的有符号数,那么同一个比较器也可以接受两个大熊猫并比较那些。因为大熊猫是动物。

所以关系

  

任何Panda都是Animal

(来自继承)导致关系

  

任何IComparer<Animal>都是IComparer<Panda>

(通过逆转)。

对于协方差的示例,具有相同的关系

  

任何Panda都是Animal

导致

  

任何IEnumerable<Panda>都是IEnumerable<Animal>

通过协方差(IEnumerable<out T>)。

相关问题