2017-04-06 18 views
5

我有點被typechecker的嚴格低於—困惑似乎的Inv[T]不變T位置也Variantish的參數列表中不變的:爲什麼所有不變的泛型類位置在Scala中的類型參數列表中都是不變的?

scala> class Inv[T] 
defined class Inv 

scala> class Variantish[+T, +TVar <: Inv[T]] 
<console>:12: error: covariant type T occurs in invariant position in type <: Inv[T] of type TVar 
     class Variantish[+T, +TVar <: Inv[T]] 
          ^

變異類型,通常可發生於什麼樣子像法律上不變的參數列表位置,例如與保護對象的可見性:

class Variantish[+T](protected[this] var v: Inv[T]) 

,似乎下面會是一樣的類型安全:該檢查上述那麼嚴格

class Variantish[+T, +TVar <: Inv[T]](protected[this] var v: TVar) 

極品?

回答

1

從語言specification(重點煤礦),約一致性(即T'是超型T):

類型構造TT′遵循類似的紀律。我們通過它們的類型參數子句[a1,…,an][a′1,…,a′n]來表徵TT′,其中aia′i可以包括方差標註,高階類型參數子句和邊界。然後,T符合T′如果任何名單[t1,…,tn] - 與申報差異,邊界和高階類型參數子句 - 有效類型參數T′也是類型參數TT[t1,…,tn]<:T′[t1,…,tn]一個有效的列表。

這實在是很難理解(恕我直言),但我相信它意味着VariantishT被協變的,你必須能夠寫

Variantish[Dog, TVar] <: Variantish[Animal, TVar] 

任何TVar其中Variantish[Animal, TVar]是有意義的。但對於TVar中的一些,例如Inv[Animal],這甚至沒有意義(更不用說有任何真值)。這就是爲什麼它被禁止在那個地方。

0

我不太明白@ cyrille-corpet的答案,所以我用一些例子擴展了它。

​​

a是有效的,因爲Animal <:AnimalAnimalInv <:AnimalInv都是真實的。

bDogInv <:AnimalInv錯誤無效。

c是有效的,因爲Dog <:AnimalAnimalInv <:AnimalInv都是真實的。

d是無效的,因爲DogInv <:AnimalInv是假的。

因此,這些顯示TVar不能協變。

即使在動態類型有效的d的情況下,它也不是靜態類型的子類型。

我懷疑如果我們看看我們可能使用的所有地方TVarVariantish那麼它不需要是類型參數。正如@concat指出的,您可能會遇到的任何差異錯誤都可以通過使用受保護的對象訪問修飾符來解決。

相關問題