2017-10-09 67 views
10

考慮下面的代碼片段:無法推斷逆變全無類型參數

trait X[-T] 
object Y extends X[Nothing] 
def a[T](x: X[T]): X[T] = x 
a(Y) 

以上(2.12.3)的編譯失敗:

type mismatch; 
found : Y.type 
required: X[T] 
    a(Y) 
    ^

編譯沒有問題,如果:

  • 使用與Nothing不同的類型(例如object Y extends X[String]
  • 方法a在其返回類型中不使用T(例如, def a[T](x: X[T]): Unit = {}
  • a類型參數明確給出(即a[Nothing](Y)
  • T是協變,不逆變(也失敗,如果它是不變的)

這是編譯器爲Nothing一些特殊的情況下?

作爲一個「有趣」的變通,下面似乎很好地工作:

trait X[-T] 
object Y extends X[Nothing] 
def a[T, U <: T](x: X[T]): X[U] = x 
a(Y) 

回答

1

我會嘗試通過行解釋代碼行

線路1:trait X[-T] - >特徵X是在T類型中是不變的。所以你可以用它的子類型來替換任何類型爲X [T]的變量。在逆變類型的情況下,如果B是A的子類型,Z [A]是Z [B]的子類型。

線2:object Y extends X[Nothing]→對象Y是X型[無]。請注意,Nothing是所有其他類型的子類型。

第3行:def a[T](x: X[T]): X[T] = x - >定義一個表達式,它接受X [T]類型的參數。因爲特徵X在類型T中是逆變的,所以還可以傳遞X [T]的子類型,即X [N]使得T是N的子類型

第4行:a(Y) - >用參數類型調用表達式'a' X [沒什麼]。由於編譯器不知道'a'參數的類型,因此無法確定X [Nothing]是否爲X [T]的子類型。有多種方法可以解決這個問題

Solution 1: `a[Nothing]` -> explicitly defining the type 

Solution 2: `tait X[+T]` -> make X covariant in type T. In this case Z[A] is subtype of Z[B] if A is subtype of B. This will work because Nothing is subtype of any other type 
+0

感謝您的回答,但爲什麼使用String而不是Nothing來讓示例編譯?或者爲什麼解決方法工作? – adamw