Scala Option类型上界不明白
Scala Option type upper bound don't understand
我正在阅读 Scala 中的函数式编程,在第 4 章中,作者自己实现了 Option。现在,在定义函数 getOrElse
时,他们使用上限将 A
的类型限制为超类型(如果理解正确的话)
所以,定义是:
sealed trait Option[+A] {
def getOrElse[B >: A](default: => B): B = this match {
case None => default
case Some(a) => a
}
}
所以,当我们有类似
的东西时
val a = Some(4)
println(a.getOrElse(None)) => println prints a integer value
val b = None
println(b.getOrElse(Some(3)) => println prints a Option[Integer] value
a
的类型为 Option[Int]
,因此 A
的类型为 Int
。 B
将是类型 Nothing
。 Nothing
是所有其他类型的子类型。这意味着 Option[Nothing]
是 Option[Int]
的子类型(因为协方差),对吧?
但是对于 B >: A
我们说 B
必须是超类型?!那么我们怎样才能得到 Int
呢?这让我有点困惑......
有人愿意尝试澄清一下吗?
That means that Option[Nothing] is a subtype of Option[Int] (because of covariance), right?
正确。 Option[Nothing]
是一个 Option[Int]
.
But with B >: A we said that B has to be a supertype?! So how can we get an Int back?
它不一定是超类型。它只需要 A
作为 下限 。这意味着如果 A
是 Int
,您仍然可以将 Int
传递给 getOrElse
。
但这并不意味着您不能传递子实例class。例如:
class A
class B extends A
class C extends B
scala> Option(new B)
res196: Option[B] = Some(B@661f82ac)
scala> res196.getOrElse(new C)
res197: B = B@661f82ac
scala> res196.getOrElse(new A)
res198: A = B@661f82ac
scala> res196.getOrElse("...")
res199: Object = B@661f82ac
我仍然可以传递 C
的实例,因为 C
可以向上转换为 B
。我还可以将类型传递到继承树的更高层,getOrElse
将 return 改为该类型。如果我传递的类型与 Option
中包含的类型无关,那么将推断具有最小上限的类型。在上面的例子中,它是 Any
.
那么为什么会有下界呢?为什么没有:
def getOrElse[B <: A](default: => B): B
这行不通,因为 getOrElse
必须 return Option
中包含的 A
或默认值 B
。但是如果我们 return 是 A
,而 A
不是 B
,那么类型绑定是无效的。也许如果 getOrElse
returned A
:
def getOrElse[B <: A](default: => B): A
这会起作用(如果它确实以这种方式定义的话),但是您会受到类型限制的限制。所以在我上面的例子中,你只能在 Option[B]
上将 B
或 C
传递给 getOrElse
。无论如何,这不是标准库中的方式。
标准库getOrElse
允许您向其传递任何内容。假设您有 Option[A]
。如果我们传递 A
的子类型,那么它会向上转换为 A
。如果我们通过 A
,显然这是可以的。如果我们传递一些其他类型,那么编译器会推断出两者之间的最小上限。在所有情况下,都满足类型绑定 B >: A
。
因为 getOrElse
允许您将任何东西传递给它,许多人认为它非常棘手。例如你可以有:
val number = "blah"
// ... lots of code
val result = Option(1).getOrElse(number)
这将编译。我们只有一个 Option[Any]
可能会在其他地方引起错误。
我正在阅读 Scala 中的函数式编程,在第 4 章中,作者自己实现了 Option。现在,在定义函数 getOrElse
时,他们使用上限将 A
的类型限制为超类型(如果理解正确的话)
所以,定义是:
sealed trait Option[+A] {
def getOrElse[B >: A](default: => B): B = this match {
case None => default
case Some(a) => a
}
}
所以,当我们有类似
的东西时val a = Some(4)
println(a.getOrElse(None)) => println prints a integer value
val b = None
println(b.getOrElse(Some(3)) => println prints a Option[Integer] value
a
的类型为 Option[Int]
,因此 A
的类型为 Int
。 B
将是类型 Nothing
。 Nothing
是所有其他类型的子类型。这意味着 Option[Nothing]
是 Option[Int]
的子类型(因为协方差),对吧?
但是对于 B >: A
我们说 B
必须是超类型?!那么我们怎样才能得到 Int
呢?这让我有点困惑......
有人愿意尝试澄清一下吗?
That means that Option[Nothing] is a subtype of Option[Int] (because of covariance), right?
正确。 Option[Nothing]
是一个 Option[Int]
.
But with B >: A we said that B has to be a supertype?! So how can we get an Int back?
它不一定是超类型。它只需要 A
作为 下限 。这意味着如果 A
是 Int
,您仍然可以将 Int
传递给 getOrElse
。
但这并不意味着您不能传递子实例class。例如:
class A
class B extends A
class C extends B
scala> Option(new B)
res196: Option[B] = Some(B@661f82ac)
scala> res196.getOrElse(new C)
res197: B = B@661f82ac
scala> res196.getOrElse(new A)
res198: A = B@661f82ac
scala> res196.getOrElse("...")
res199: Object = B@661f82ac
我仍然可以传递 C
的实例,因为 C
可以向上转换为 B
。我还可以将类型传递到继承树的更高层,getOrElse
将 return 改为该类型。如果我传递的类型与 Option
中包含的类型无关,那么将推断具有最小上限的类型。在上面的例子中,它是 Any
.
那么为什么会有下界呢?为什么没有:
def getOrElse[B <: A](default: => B): B
这行不通,因为 getOrElse
必须 return Option
中包含的 A
或默认值 B
。但是如果我们 return 是 A
,而 A
不是 B
,那么类型绑定是无效的。也许如果 getOrElse
returned A
:
def getOrElse[B <: A](default: => B): A
这会起作用(如果它确实以这种方式定义的话),但是您会受到类型限制的限制。所以在我上面的例子中,你只能在 Option[B]
上将 B
或 C
传递给 getOrElse
。无论如何,这不是标准库中的方式。
标准库getOrElse
允许您向其传递任何内容。假设您有 Option[A]
。如果我们传递 A
的子类型,那么它会向上转换为 A
。如果我们通过 A
,显然这是可以的。如果我们传递一些其他类型,那么编译器会推断出两者之间的最小上限。在所有情况下,都满足类型绑定 B >: A
。
因为 getOrElse
允许您将任何东西传递给它,许多人认为它非常棘手。例如你可以有:
val number = "blah"
// ... lots of code
val result = Option(1).getOrElse(number)
这将编译。我们只有一个 Option[Any]
可能会在其他地方引起错误。