Scala Co和Contravariance

时间:2016-04-06 18:55:05

标签: scala covariance contravariance

是的!另一个问题,是的,我已经在stackoverflow中阅读了很多这样的问题,但仍然不理解这个概念及其应用。

所以,我是Scala的新人,像许多人一样,我仍然没有得到Contravariance的概念,我正在阅读Programming Scala,第2版,并在第283页开始解释co和与以下例子相反:

给出了层次结构:

class CSuper { def msuper() = println("CSuper") }
class C extends CSuper { def m() = println("C") }
class CSub extends C { def msub() = println("CSub") }

然后有一个函数和一些使用示例:

var f: C => C = (c: C) => new C
    f         = (c: CSuper) => new CSub
    f         = (c: CSuper) => new C
    f         = (c: C) => new CSub
    f         = (c: CSub) => new CSuper // COMPILATION ERROR!

在java中思考我知道最后一个表达式不会编译,因为CSuper是CSub的超类型。

我不明白的是什么意味着一个类型,在这种情况下,Function1 [-C,+ C]在第一个参数中是逆变的?

这本书说,逆向就是where X[String] is a supertype of X[Any], for some type X.

共/变量只适用于参数化类型的子类,我的意思是因为我们使用的是Function1,因此方差仅适用于Function1的子类型,是吗?

它是如何实际工作的,我应该何时使用/需要它?

1 个答案:

答案 0 :(得分:2)

  

如果T'是T的子类,那么Container [T']是否被认为是Container [T]的子类?

     

[+T] 协变:C [T']是C [T]的子类,
  [-T] 逆变: C [T]是C [T']的子类

Function1定义为trait Function1[-T1, +R],因此参数是逆变的,结果类型是协变的。

这意味着,那些函数,哪个参数是给定函数的参数类型的超类型,哪个结果类型是给定函数的结果类型的子类型本身是子类型给定功能。

在您的示例中,当您将不同的函数声明分配给f类型的C => C时,只会分配有效的子类型。

即,只有这些函数声明是C => C的有效子类型:

var f: C => C = (c: C) => new C
f         = (c: C) => new C
f         = (c: C) => new CSub
f         = (c: CSuper) => new C
f         = (c: CSuper) => new CSub

其他所有内容都是C => C的超类型,无法分配到f或不相关的类型。