2011-12-12 137 views

回答

17

你不能有var的協變類型。 一個var等於有一個公衆def v_=(newV: T),所以它使T顯示爲一個常規參數,這是一個逆變位置。所以,你必須要麼

  • 宣佈放棄協方差,並宣佈C [T],而不是C [+ T]
  • 化妝VA VAL

要上的 「爲什麼」 的部分一點點更詳細的你的問題,通過使T是與T的協變參數,如果B是A的子類型,則表明你希望C [B]爲C [A]的子類型。這意味着您想要允許:

val cb: C[B] = new C[B] 
val ca : C[A] = cb  

爲了讓這聽起來,編譯器限制T可能出現在C中的位置。爲了簡化和簡化,v不能作爲例程的參數(或var的類型)出現。否則,您必須初始化CB和Ca描述後,你上面coulddo

ca.v = new A 

這是允許的,因爲ca應該是一個C[A],所以它的可變vA類型。然而,由於C在T中是協變的,因此ca可能(並且在該示例中)引用C[B]實例。將這項任務被允許,你可以再做

val vInCb: B = cb.v 

信心,這給你一個。但是,您只需通過ca參考即可將A。這種情況必須被禁止,並且通過禁止協變類型參數T作爲var的類型。

+0

還有第三種選擇... –

+0

非常感謝丹尼爾,我寫了私人的第三個變體,並在測試後刪除它,我忘記了[這個] –

2

你必須使它成爲val。 A var總是有一個setter方法,其中類型以逆變位置出現。

9

你可以把它聲明爲private[this]

class C [+T] { private[this] var v : T = _ } 

你試試這個範圍不允許將是不安全與共變T任何使用。