混淆了方差

ssa*_*anj 3 scala variance

鉴于以下内容:

trait Fruit

class Apple extends Fruit
class Orange extends Fruit

case class Crate[T](value:T)

def p(c:Crate[Fruit]) {  }

val cra = Crate(new Apple)
val cro = Crate(new Orange)
Run Code Online (Sandbox Code Playgroud)

由于Crate是不变的,我不能做以下(如预期的那样):

scala> val fruit:Crate[Fruit] = cra
<console>:10: error: type mismatch;
 found   : Crate[Apple]
 required: Crate[Fruit]
       val fruit:Crate[Fruit] = cra
                                ^

scala> val fruit:Crate[Fruit] = cro
<console>:10: error: type mismatch;
 found   : Crate[Orange]
 required: Crate[Fruit]
       val fruit:Crate[Fruit] = cro

scala> p(cra)
<console>:12: error: type mismatch;
 found   : Crate[Apple]
 required: Crate[Fruit]
       p(cra)
         ^

scala> p(cro)
<console>:12: error: type mismatch;
 found   : Crate[Orange]
 required: Crate[Fruit]
       p(cro)
Run Code Online (Sandbox Code Playgroud)

但是当Crate不协变时,为什么我可以用这些来调用方法p?:

scala> p(Crate(new Apple))
Crate(line2$object$$iw$$iw$Apple@35427e6e)

scala> p(Crate(new Orange))
Crate(line3$object$$iw$$iw$Orange@33dfeb30)
Run Code Online (Sandbox Code Playgroud)

我是否错过了一些基本的差异原则?

Rex*_*err 6

在后一种情况下,编译器假定您希望它能够正常工作并实际说明

p(Crate( (new Apple): Fruit ))
Run Code Online (Sandbox Code Playgroud)

这是完全可以的.就像你手动做的一样

val f: Fruit = new Apple   // totally fine
p(Crate(f))                // Also totally fine
Run Code Online (Sandbox Code Playgroud)

这只是编译器应用的巨大魔法的一小部分,试图找出你对你的类型的意思,而不是让你输入它.