Mar*_*rin 5 type-systems scala optional
我正在阅读Scala中的Functional Programming,在第04章中,作者自己实现了Option.现在,在定义函数时,getOrElse他们使用上限将类型限制A为超类型(如果正确理解)
所以,定义如下:
sealed trait Option[+A] {
def getOrElse[B >: A](default: => B): B = this match {
case None => default
case Some(a) => a
}
}
Run Code Online (Sandbox Code Playgroud)
所以,当我们有类似的东西时
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
Run Code Online (Sandbox Code Playgroud)
a有类型Option[Int],所以A是类型Int.B将是类型Nothing.Nothing是每种其他类型的子类型.这意味着它Option[Nothing]是Option[Int](由于协方差)的子类型,对吧?
但是B >: A我们说过B必须要超类型?!那我们怎么能Int回来呢?这对我来说有点混乱......
有人关心尝试澄清吗?
这意味着Option [Nothing]是Option [Int]的子类型(因为协方差),对吧?
正确.Option[Nothing]是一个Option[Int].
但是B>:A我们说B必须是超类型?!那么我们如何才能获得Int?
它不一定是超类型.它只需要A作为一个下限.这意味着你仍然可以传递Int到getOrElse如果A是Int.
但这并不意味着你不能传递子类的实例.例如:
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
Run Code Online (Sandbox Code Playgroud)
我仍然可以传递一个实例C,因为C可以向上传播B.我也可以在继承树中传递一个更高的类型,然后getOrElse返回该类型.如果我传递的类型与包含的类型无关Option,那么将推断出具有最小上限的类型.在上面的例子中,它是Any.
那么为什么那里的下限呢?为什么没有:
def getOrElse[B <: A](default: => B): B
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为getOrElse必须返回A包含在其中的Option,或默认值B.但是如果我们返回A,而A不是a B,那么类型绑定是无效的.也许如果getOrElse退回A:
def getOrElse[B <: A](default: => B): A
Run Code Online (Sandbox Code Playgroud)
这可以工作(如果它确实是这样定义的),但你会受到类型边界的限制.所以在我上面的例子中,你只能通过B或C以getOrElse上Option[B].无论如何,这不是标准库中的方式.
标准库getOrElse允许您传递任何内容.说你有Option[A].如果我们传递一个子类型A,那么它是向上转换的A.如果我们通过A,显然这是可以的.如果我们传递其他类型,那么编译器会推断出两者之间的最小上限.在所有情况下,B >: A都满足类型绑定.
因为getOrElse允许你传递任何东西,许多人认为它非常棘手.例如,您可以:
val number = "blah"
// ... lots of code
val result = Option(1).getOrElse(number)
Run Code Online (Sandbox Code Playgroud)
这将编译.我们只会有一个Option[Any]可能会在其他地方引起错误.
| 归档时间: |
|
| 查看次数: |
341 次 |
| 最近记录: |