问题描述
在 Scala 的上限概念中,可以传递给定类型或其超类型。例如,在下面的方法中,S 是类型,A 是我们传递的参数。该方法实际上接受 Scala 类型系统中存在的所有值。 S、S亚型及其超型。这是因为所有类型都扩展了 Any 类型。
def method[A >: S](a:A) = { ... }
那为什么我们不能把所有的上界符号都写成 Any(这是 Scala 中的通用类型)。上面的定义可以改写为:
def met(a:Any) = { ... }
这很容易理解。
上限带来什么样的优势?
谢谢!
解决方法
与转到 Any
相比,它使您丢失的类型信息更少。
例如,如果您让 Dog 和 Cat 继承 Animal,则此方法有效:
val maybeDog: Option[Dog] = ???
val pet = maybeDog.getOrElse(Cat())
因为getOrElse
的签名是def getOrElse[B >: A](default: => B): B
,所以推断B
是Animal
(作为Cat和Dog的最小上界),所以静态类型val pet
是 Animal
。如果它使用 Any
,结果将需要不安全的转换才能进一步工作。如果不完全引入新的类型参数,您将不得不编写 (maybeDog: Option[Animal]).getOrElse(Cat())
以实现相同的统一。
此外,它限制了实现不能做一些完全愚蠢的事情。例如,这种类型检查:
def getOrElse[A](option: Option[A])(default: => Any): Any = 42 // Int is Any,so why not?
虽然没有:
def getOrElse[A,B >: A](option: Option[A])(default: => B): B = 42
因为虽然任何事物都可以变成B
,但这并不意味着 Int 总是 B 的子类型。