Scala 上界表示法接受所有类型(不仅是超类型)
Scala upper bound notation accepts all types (not only super type)
在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 的子类型.
在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 的子类型.