2010-02-25 87 views
11

我試過兩種方法將泛型類型參數約束爲可空類型,但兩者似乎都有一些意想不到的問題。Scala對可爲空類型的泛型約束如何工作

第一次嘗試(使用T- <:AnyRef):

scala> def testAnyRefConstraint[T <: AnyRef](option:Option[T]):T = { 
    | //without the cast, fails with compiler error: 
    | // "found: Null(null) required: T" 
    | option getOrElse null.asInstanceOf[T] 
    | } 
testAnyRefConstraint: [T <: AnyRef](Option[T])T 

scala> testAnyRefConstraint(Some("")) 
res0: java.lang.String = 

scala> testAnyRefConstraint(Some(0)) 
<console>:16: error: inferred type arguments [Int] do not conform to method testAnyRefConstraint's type parameter bounds [T <: AnyRef] 
     testAnyRefConstraint(Some(0)) 

這似乎做的正是我想要的,但我不明白爲什麼空需要被轉換爲T.


第二次嘗試(使用T>:空):

scala> def testNullConstraint[T >: Null](option:Option[T]):T = { 
    | option getOrElse null 
    | } 
testNullConstraint: [T >: Null](Option[T])T 

scala> testNullConstraint(Some("")) 
res2: java.lang.String = 

scala> testNullConstraint(Some(0)) 
res3: Any = 0 

這並不需要對空的投,但它允許AnyVals被傳遞並將類型轉換爲任何類型,這不是我正在尋找的。

有沒有人有任何想法,爲什麼這兩種不同的方法工作,他們這樣做?

回答

20
def testAnyRefConstraint[T >: Null <: AnyRef](option:Option[T]):T = { 
    option getOrElse null 
} 

當我第一次犯這個錯誤時,我覺得真的很愚蠢。僅僅因爲延伸AnyRef並不意味着它必須是空的。例如,NothingAnyRef的子類型,它不是可空的。

其他的方法是相似的,因爲Any是超類型Null,並且任何Int也是Any