如何理解Scala Option中的超类型与方差?以getOrElse方法为例
理解Scala Option中超类型与方差的应用——以getOrElse方法为例
咱们先从Option的定义入手,再拆解getOrElse的泛型设计,最后结合实际代码例子,就能把这个问题搞明白。
1. Option的协变特性
首先看Option的核心定义:
sealed abstract class Option[+A] extends Product with Serializable { self => @inline final def getOrElse[B >: A](default: => B): B = if (isEmpty) default else this.get }
这里的+A是协变标记,直白点说就是:如果X是A的子类,那Option[X]可以直接当作Option[A]来用。比如Option[B](B extends A)是Option[A]的子类型,这在处理多态场景时特别实用。
2. getOrElse的B >: A到底有啥用?
getOrElse方法里的[B >: A],字面意思是B必须是A的超类型(或者A本身)。这个设计的核心目的是统一返回值类型:
- 如果Option是空的,返回传入的默认值
default(类型是B) - 如果Option非空,返回
this.get(类型是A)
因为A是B的子类型(A <: B),所以this.get可以安全地向上转型为B,这样两种分支的返回值类型就统一成了B,彻底避免了类型不匹配的问题。
3. 为啥实际使用中返回值可以是A的子类型或超类型?
很多人会疑惑:既然要求B是A的超类型,为啥实际代码里能返回子类型?这其实是Scala类型推断结合Option协变特性带来的灵活表现:
情况1:返回A的超类型
当我们给Option[A]传入一个超类型的默认值时,Scala会自动把B推断为这个超类型:
class SuperA class A extends SuperA val opt: Option[A] = None // 这里B被推断为SuperA,满足SuperA >: A的要求 val res: SuperA = opt.getOrElse(new SuperA)
情况2:返回A的子类型
当Option的实际类型是Option[B](B extends A),调用getOrElse时Scala可以把B推断为B本身(因为B >: B完全符合条件),这时返回值就是子类型:
class A class B extends A val opt: Option[B] = Some(new B) // 这里B被推断为B,返回值类型是B val res: B = opt.getOrElse(new B)
甚至如果给Option[B]传入A类型的默认值,Scala会把B推断为A,返回值就变成了A:
val res: A = opt.getOrElse(new A)
总结
- Option的协变
+A让它支持多态赋值,子类Option可以直接当作父类Option使用 - getOrElse的
B >: A保证了无论返回Option内的值还是默认值,类型都能统一到共同的超类型B - 类型推断让我们不用显式指定
B,Scala会根据传入的默认值和Option的实际类型自动推断最合适的B,所以看起来既可以返回子类型也可以返回超类型
内容的提问来源于stack exchange,提问作者bbarker
相关产品推荐
相关产品推荐

