Scala Co 和逆变

Scala Co and Contravariance

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

所以,我是 Scala 的新手,和许多人一样,我仍然不了解逆变的概念,我正在阅读 Programming Scala, 2nd Edition,并在第 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.

co / contravariance 仅适用于参数化类型的子类,我的意思是因为我们使用的是 Function1,所以方差仅适用于 Function1 的子类型,对吗?

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

if T’ is a subclass of T, is Container[T’] considered a subclass of Container[T]?

[+T] covariant: C[T’] is a subclass of C[T],
[-T] contravariant: C[T] is a subclass of C[T’]

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

这意味着,那个函数,其参数是给定函数参数类型的超类型,结果类型是结果的子类型给定函数的类型本身就是给定函数的子类型。

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

即,只有这些函数声明是 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 或不相关的类型。