如何确定类型参数的方差?

Bra*_*ord 11 types scala covariance contravariance generic-variance

灵感来自现实世界中Scala的共同和逆转的例子,我认为一个更好的问题是:

在设计库时,在确定类型参数是应该是协变还是逆变时,是否应该问自己一组特定的问题?或者你应该让一切都不变,然后根据需要改变?

Dan*_*ral 16

嗯,简单,有意义吗?想想利斯科夫的替代.

联合方差

如果A <: B,通过预期的C[A]地方C[B]是否有意义?如果是这样,那就去吧C[+T].经典的例子是不可变的List,其中a List[A]可以传递给期望a的任何东西List[B],假设A是子类型B.

两个反例:

可变序列是不变的,因为否则可能会发生类型安全违规(事实上,Java的共变体Array很容易受到这类事物的影响,这就是它在Scala中不变的原因).

不可变Set是不变的,即使它的方法是非常相似的一个不可改变的Seq.区别在于contains,Any在序列上键入和无类型(即,接受).因此,即使否则可能使其变为共变体,对特定方法的类型安全性的增加的期望导致对共方差的不变性的选择.

孔特拉方差

如果A <: B,通过预期的C[B]地方C[A]是否有意义?如果是这样,那就去吧C[-T].经典的例子就是Ordering.虽然一些不相关的技术问题可以防止Ordering变形,但直观的是任何可以订购超级类别的东西A都可以订购A.接下来Ordering[B],命令所有类型的元素B,超类型A,可以传递给期望的东西Ordering[A].

虽然Scala Ordering不是反式变体,但Scalaz命令是预期的变形.Scalaz的另一个例子是它的Equal特征.

混合方差?

Scala中最明显的混合方差示例是Function1(和2,3等).它在接收的参数中是反变量的,并且在它返回的内容中是共变的.但是请注意,Function1这是用于许多闭包的,并且闭包在很多地方使用,而这些地方通常是Java使用(或将使用)单个抽象方法类的地方.

因此,如果您有SAM类适用的情况,那么这可能是混合反方差和协方差的一个地方.