2011-04-11 56 views
3

鑑於以下困惑:與方差

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與這些當箱子不協變? :

scala> p(Crate(new Apple)) 
Crate([email protected]) 

scala> p(Crate(new Orange)) 
Crate([email protected]) 

我錯過了一些基本的方差原理嗎?

回答

6

在後者的情況下,編譯器假定你想要這個工作,實際上說的

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

這是完全沒問題。這是一樣的,如果你手動做

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

這是編譯器適用於揣摩你與你的類型是什麼意思,而不讓你輸入這一切了巨大魔力的只是一小部分。

+0

謝謝。幾乎看起來好像編譯器將方法p的Crate的不變性短路,當它假定開發人員希望它工作時。我認爲Crate必須被定義爲Crate [+ T]才能讓p方法與cro,cra一起工作。 – ssanj 2011-04-11 00:59:05

+1

@ssanj - 你說得對,它必須被定義爲'+ T'來處理'cro'和'cra',它們已經分配了它們的類型。但是當你沒有指定類型併產生新的東西時,它假定你想要一些明智的東西,如果有明智的東西可以得到。 – 2011-04-11 01:07:47