开发者

Confused with Variance

Given the following:

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)

since Crate 开发者_高级运维is invariant, I can't do the following (as expected):

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)

But why can I call method p with these when Crate is not covariant? :

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

scala> p(Crate(new Orange))
Crate(line3$object$$iw$$iw$Orange@33dfeb30)

Have I missed some basic principles of variance?


In the latter cases, the compiler assumes that you want this to work and actually says

p(Crate( (new Apple): Fruit ))

which is perfectly okay. It's the same as if you manually did

val f: Fruit = new Apple   // totally fine
p(Crate(f))                // Also totally fine

This is just a small part of the immense wizardry that the compiler applies to try to figure out what you mean with your types without making you type it all out.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜