2014-12-13 73 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[_]