灵感来自Scala 中协变和逆变的现实示例 https://stackoverflow.com/questions/5277526/real-world-examples-of-co-and-contravariance-in-scala我认为更好的问题是:
在设计库时,在确定类型参数应该是协变还是逆变时,您是否应该问自己一组特定的问题?或者你应该让一切保持不变,然后根据需要进行更改?
嗯,很简单,有道理吗?想想里氏替换。
协方差
If A <: B
,通过一个有意义吗?C[A]
其中一个C[B]
是期待?如果是的话,就做它C[+T]
。经典的例子就是不可变的List
,其中一个List[A]
可以传递给任何期待List[B]
, 假设A
是一个子类型B
.
两个反例:
可变序列是不变的,因为否则可能会出现类型安全违规(事实上,Java 的协变Array
很容易受到这样的事情的影响,这就是为什么它在 Scala 中是不变的)。
不可变的Set
是不变的,尽管它的方法与不可变的方法非常相似Seq
。区别在于contains
,它是在集合上键入的并且是非类型化的(即接受Any
)在序列上。因此,即使可以使其成为协变,但对特定方法增加类型安全性的渴望导致选择不变性而不是协变。
逆变
If A <: B
,通过一个有意义吗?C[B]
其中一个C[A]
是期待?如果是的话,就做它C[-T]
。经典的例子是Ordering
。虽然一些不相关的技术问题阻止了Ordering
从逆变性来看,直观的是任何可以订购超类的东西A
也可以订购A
。它遵循Ordering[B]
,对类型的所有元素进行排序B
,一个超类型A
,可以传递给期待的东西Ordering[A]
.
而斯卡拉的Ordering
不是逆变的,Scalaz http://code.google.com/p/scalaz/'s Order http://scalaz.googlecode.com/svn/continuous/latest/browse.sxr/scalaz/Order.scala.html正如预期的那样是逆变的。 Scalaz 的另一个例子是Equal http://scalaz.googlecode.com/svn/continuous/latest/browse.sxr/scalaz/Equal.scala.html trait.
混合方差?
Scala 中混合方差最明显的例子是Function1
(以及 2、3 等)。它接收的参数是逆变的,返回的参数是协变的。但请注意,Function1
是用于很多闭包的东西,闭包被用在很多地方,这些地方通常是Java使用(或将使用)单一抽象方法类的地方。
因此,如果您遇到 SAM 类适用的情况,那么这可能是混合逆变和协方差的地方。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)