2015-04-27 30 views
5

我正在閱讀Scala中的函數式編程,而在第04章中,作者自己實現了Option。現在,定義函數getOrElse當他們使用一個上限的A類型限制的父(如果理解正確的)Scala選項類型上限不明白

所以,定義雲:

sealed trait Option[+A] { 
    def getOrElse[B >: A](default: => B): B = this match { 
    case None => default 
    case Some(a) => a 
    } 
} 

所以,當我們有一些像

val a = Some(4) 
println(a.getOrElse(None)) => println prints a integer value 
val b = None 
println(b.getOrElse(Some(3)) => println prints a Option[Integer] value 

a具有類型Option[Int],所以AInt類型。 B將是類型NothingNothing是每個其他類型的子類型。這意味着Option[Nothing]Option[Int]的一個子類型(由於協方差),對吧?我們說B必須是超類型?!那麼我們怎麼能回到Int?這對我來說有點令人困惑......

有人試圖澄清嗎?

回答

8

這意味着Option [Nothing]是Option [Int]的子類型(由於協方差),對吧?

正確。 Option[Nothing]Option[Int]

但是用B>:A我們說B必須是超類型?!那麼我們怎樣才能得到一個Int?

它不一定是超級類型。它只需要A作爲下限。這意味着如果AInt,您仍然可以通過IntgetOrElse

但這並不意味着你不能傳遞一個子類的實例。例如:

class A 
class B extends A 
class C extends B 

scala> Option(new B) 
res196: Option[B] = Some([email protected]) 

scala> res196.getOrElse(new C) 
res197: B = [email protected] 

scala> res196.getOrElse(new A) 
res198: A = [email protected] 

scala> res196.getOrElse("...") 
res199: Object = [email protected] 

我還是可以通過的C一個實例,因爲C最多可以鑄造到B。我也可以在繼承樹上傳遞更高的類型,而getOrElse將返回該類型。如果我傳遞的類型與Option中包含的類型無關,那麼將推斷具有最小上限的類型。在上述情況下,它是Any


那麼,爲什麼那裏的下限呢?爲什麼不能有:

def getOrElse[B <: A](default: => B): B 

這不會起作用,因爲getOrElse必須要麼返回真實包含在OptionA,或默認B。但是,如果我們返回A,A不是B,那麼類型綁定無效。也許,如果getOrElse返回A

def getOrElse[B <: A](default: => B): A 

這將工作(如果它真的被定義的方式),但你會被類型範圍受到限制。所以在我上面的例子中,你只能通過BCgetOrElseOption[B]。無論如何,這不是它在標準庫中的樣子。


標準庫getOrElse讓你任何東西傳遞給它。假設你有Option[A]。如果我們通過A的子類型,則將其上傳到A。如果我們通過A,顯然這沒關係。如果我們通過其他類型,那麼編譯器會推斷出兩者之間的最小上界。在所有情況下,滿足類型限制B >: A

因爲getOrElse允許你傳遞任何東西給它,所以很多人認爲它非常棘手。例如,你可以有:

val number = "blah" 
// ... lots of code 
val result = Option(1).getOrElse(number) 

這將編譯。我們只會有一個Option[Any]這可能會導致錯誤的其他地方的錯誤。

+0

謝謝,但請您提供一個我們無法傳遞給res196.getOrElse的例子......目前,在這個例子中,我沒有看到有一個下限的觀點。或者更好地說,我現在不明白一個類型是什麼意思是一個下限...... – Marin

+0

@Marin你可以將任何類型傳遞給'getOrElse'。看我的編輯。 –

+0

謝謝!我想我現在明白了。 – Marin