要了解它为什么有用,IttayD provided a nice explanation:
所以我们想要的是 def
orNull[A >: Null] = ..... 但是 A 是
已经设置,我们不想
将其限制在定义中
特征。因此, orNull 期望一个
证明 A 是可空类型的证据。
这个证据的形式是
隐式变量(因此得名
'ev')
总之,当您希望泛型类(例如Option)上的方法(例如orNull)具有比类本身(例如@987654327)更具体的约束(例如Null <: A <: Any)时,类型约束很有用@)。
这是另一个未内置于语言中的“功能”,但由于隐式参数和类型参数的方差注释而免费提供。要理解这一点,请看<:<的定义:
// from Predef
sealed abstract class <:<[-From, +To] extends (From => To)
implicit def conforms[A]: A <:< A = new (A <:< A) {def apply(x: A) = x}
对于
scala> Some(1).orNull
<console>:10: error: could not find implicit value for parameter ev: <:<[Null,Int]
Some(1).orNull
编译器查找<:<[Null, Int] 类型的隐式值,并将找到方法def conforms[A]: A <:< A。所以必须有一个A,其中<:<[A, A] 符合<:<[Null, Int]。没有 A 成立,因此编译器会抱怨缺少隐式值。
然而,对于
scala> Some("hi").orNull
res21: java.lang.String = hi
我们很幸运。现在,编译器尝试找到一个<:<[A, A] 符合<:<[Null, String] 的A。这适用于A = String,因为Null 是String 的子类型,并且<:< 类的From 类型参数被定义为逆变的)。
如前所述,考虑类型约束的最直观方式是将其视为类型绑定(即,将其读取为 Null <: int>Null 不符合 Int 并且 <: int>Null 确实符合String,编译器会找到隐式参数。
顺便说一句,这是另一个related answer。