不,这并不是“一切正常”,请仔细查看返回值的推断类型。
宣言
B >: A
意味着:编译器将推断出最具体的类型
B
这样的论点
getOrElse
属于类型
B
同时
A
是的子类型
B
。这是另一种说法:返回类型
getOrElse公司
是
最小上界
的参数
Option
以及回退参数的类型。
您的实验证实:
scala> class A
scala> class B extends A
scala> class C extends B
scala> val optA: Option[A] = Option(null)
scala> optA.getOrElse(new B)
val res23: A = B@66a2c8e7 // LUB(A, B) = A
scala> val optB: Option[B] = Option(null)
scala> optB.getOrElse(new A)
val res24: A = A@2a460bf // LUB(B, A) = A, symmetric!
scala> optB.getOrElse(new C)
val res25: B = C@e87f97f // LUB(B, C) = B
最后一个案例当然是完全有效的,因为
new C
属于类型
C
,以及自
C <: B
,是的
而且
类型的元素
B
.没有矛盾:
B
是推断的
返回类型
,它是
不
参数的最具体类型
default
(这将是
default.type
,直接使用时基本无用)。特别是,
A.
不必是的子类型
违约类型
,这没有任何意义。
如果你系统地用A、B、C的组合进行所有实验,你会得到以下返回类型:
| A B C
--+-----
A | A A A
B | A B B
C | A B C
这本质上是元素全序集上的“最大”函数
C <: B <: A
。
简单(&A);直观的规则是:编译器和标准库中方法的函数签名非常努力地提供最具体的返回类型,并尽可能多地保留类型信息。