Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Contravariance 为什么这些逆变参数类型被认为是安全的?_Contravariance - Fatal编程技术网

Contravariance 为什么这些逆变参数类型被认为是安全的?

Contravariance 为什么这些逆变参数类型被认为是安全的?,contravariance,Contravariance,我刚刚在编程语言课上学到,“逆变参数类型实际上是安全的,但它们没有被发现是有用的,因此在实际语言中不受支持。”即使它们不受支持,我还是不明白为什么我们给出的这个例子在理论上仍然是“安全的”: 据我所知,当做了一些可能导致特异性丧失的事情时,子类型的问题就会出现。那如果我这么做呢 Panda p = new Panda(); Animal a = new Animal ... p.compare(a); 当我看到这一点时,熊猫似乎可以(而且可能确实)拥有一些普通动物不知道的额外领域。因此,即

我刚刚在编程语言课上学到,“逆变参数类型实际上是安全的,但它们没有被发现是有用的,因此在实际语言中不受支持。”即使它们不受支持,我还是不明白为什么我们给出的这个例子在理论上仍然是“安全的”:

据我所知,当做了一些可能导致特异性丧失的事情时,子类型的问题就会出现。那如果我这么做呢

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

当我看到这一点时,熊猫似乎可以(而且可能确实)拥有一些普通动物不知道的额外领域。因此,即使它们所有的动物特定数据成员都是相同的,熊猫也可能有其他不同的东西。把它和普通的动物相比怎么会好呢?它会只考虑动物的东西而忽略其他吗? 在您的示例中,您没有使用任何类型。你有
Panda
扩展
Animal
,这是一个例子,并引出了你所描述的内容。检查链接

为了得到逆变,你需要考虑一些泛型。我将使用.NET类型作为示例。使用C#语法(我将使用它而不是Java),通过在定义中写入
,我们指出
IComparer
T
中是逆变的:

public interface IComparer<in T>
{
  ...
}
现在在C#中,可以合法地说:

IComparer<Panda> myPandaComparer = CreateAnimalComparer();
IComparer myPandaComparer=CreateAnimalComparer();
现在,这是因为相反。请注意,类型
IComparer
不是从类型
IComparer
派生的(或“扩展”)。相反,
Panda
源于
Animal
,这导致
IComparer
可以相互分配(顺序相反,因此是“反向变异”(而不是“协方差”)

声明
比较器
逆变式之所以有意义,是因为如果您有一个比较器可以比较两个任意动物,并返回一个有符号的数字,指示哪个更大,那么同一个比较器还可以接收两个熊猫并比较它们。因为熊猫是动物

那么关系呢

任何
熊猫
都是
动物

(来自继承)导致关系

任何
i比较者
都是
i比较者

(相反)

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

任何
熊猫
都是
动物

导致

任何
IEnumerable
都是
IEnumerable

通过协方差(
IEnumerable

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