Путать с дисперсией - PullRequest
       19

Путать с дисперсией

3 голосов
/ 11 апреля 2011

Учитывая следующее:

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)

, поскольку ящик является инвариантом, я не могу сделать следующее (как и ожидалось):

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)

Но почему я могу вызвать метод p для них, когда Crate не является ковариантным? :

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

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

Я пропустил некоторые основные принципы дисперсии?

1 Ответ

6 голосов
/ 11 апреля 2011

В последних случаях компилятор предполагает, что вы хотите, чтобы это работало, и на самом деле говорит

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

, что совершенно нормально.Это так же, как если бы вы делали это вручную

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

Это лишь малая часть огромного волшебства, которое применяет компилятор, чтобы попытаться выяснить, что вы имеете в виду с вашими типами, не заставляя вас печатать все это.

...