2014-12-13 104 views
0

我(有點)瞭解Scala的類型系統的基礎知識,但還不夠好!爲什麼下面這兩個函數的返回類型不被認爲是等價的?類型邊界/多態混淆

trait Base[T] 
case class Foo() extends Base[Foo] 
case class Bar() extends Base[Bar] 

def willNotCompile[T <: Base[_]](x: Int): T = 
    if(x < 10) new Foo() else new Bar() 

def compilesFine(x: Int): Base[_] = 
    if(x < 10) new Foo() else new Bar() 

回答

5

類型第一函數的規定,對於所有T任何人挑選(只要它們的Base亞型),該功能可按必須返回類型T的值。後者的功能不能保證那樣,它只返回Base。 (其實我並不認爲該類型參數Base是相關的這個例子。)

例如,請考慮我的定義:

case class Baz() extends Base[Baz] 

隨後的willNotCompile類型會允許我這樣稱呼

willNotCompile[Baz](0) 

我應該找回Baz的值!很顯然,情況並非如此,所以定義不會進行類型檢查。

其他函數沒有聲明返回任何比Base更具體的類型,所以沒有問題。

FWIW,這個例子表明參數多態性(又名「泛型」)比單純的子類型更具表現力。

2

返回類型willNotCompile由調用者決定。因此,T可能不是超類型FooBar,因此它不會編譯(考慮case class Baz() extends Base[Baz]; willNotCompile[Baz](42))。

返回類型compilesFine始終爲Base[_]