Scala 类型推断和隐式转换
Scala type inference and implicit conversions
以下代码有效:
scala> import scala.language.implicitConversions
import scala.language.implicitConversions
scala> implicit val longToInt = (l: Long) => l.toInt
longToInt: Long => Int = $$Lambda21/0x000000010086e840@52bd9a27
scala> def printInt(n: Int) = println(n)
printInt: (n: Int)Unit
scala> val opt: Option[Long] = None
opt: Option[Long] = None
scala> val n = opt.getOrElse(0L)
n: Long = 0
scala> printInt(n)
0
但是,如果我们在函数调用中嵌套 getOrElse
表达式,编译器会抛出类型不匹配错误:
scala> printInt(opt.getOrElse(0L))
<console>:16: error: type mismatch;
found : AnyVal
required: Int
printInt(opt.getOrElse(0L))
^
为什么 opt.getOrElse(0L)
的类型是 AnyVal?
Scala 2.12.8
getOrElse的签名是:
def getOrElse[B1 >: B](key: A, default: ⇒ B1): B1
printInt(opt.getOrElse(0L)) 告诉 Scala B1 应该是 Long,但 Long 不是 Int 的超类型。通用超类型是 AnyVal。因此,您不能进行该分配。
尝试将结果转换为 Long:
printInt(opt.getOrElse(0L).toLong)
当你写
printInt(opt.getOrElse(0L))
opt.getOrElse(0L)
的类型为预期类型 Int
。 Option#getOrElse
's signature is
getOrElse[B >: A](default: ⇒ B): B
因为它是通用的,所以编译器会尝试找到 B
,使得 opt.getOrElse[B](0L)
具有类型 Int
。所以B
必须满足约束B >: Long
(因为上面签名中的A
是Long
)和B <: Int
(来自return类型)。显然没有这样的B
。 Scala 规范说这一定是一个错误,但没有说是哪个错误,而这里编译器恰好在猜测 B = AnyVal
.
后报告它。
另一种解决方法是指定 opt.getOrElse(0L)
的预期类型:
printInt(opt.getOrElse(0L): Long)
或类型参数:
printInt(opt.getOrElse[Long](0L))
以下代码有效:
scala> import scala.language.implicitConversions
import scala.language.implicitConversions
scala> implicit val longToInt = (l: Long) => l.toInt
longToInt: Long => Int = $$Lambda21/0x000000010086e840@52bd9a27
scala> def printInt(n: Int) = println(n)
printInt: (n: Int)Unit
scala> val opt: Option[Long] = None
opt: Option[Long] = None
scala> val n = opt.getOrElse(0L)
n: Long = 0
scala> printInt(n)
0
但是,如果我们在函数调用中嵌套 getOrElse
表达式,编译器会抛出类型不匹配错误:
scala> printInt(opt.getOrElse(0L))
<console>:16: error: type mismatch;
found : AnyVal
required: Int
printInt(opt.getOrElse(0L))
^
为什么 opt.getOrElse(0L)
的类型是 AnyVal?
Scala 2.12.8
getOrElse的签名是:
def getOrElse[B1 >: B](key: A, default: ⇒ B1): B1
printInt(opt.getOrElse(0L)) 告诉 Scala B1 应该是 Long,但 Long 不是 Int 的超类型。通用超类型是 AnyVal。因此,您不能进行该分配。
尝试将结果转换为 Long:
printInt(opt.getOrElse(0L).toLong)
当你写
printInt(opt.getOrElse(0L))
opt.getOrElse(0L)
的类型为预期类型 Int
。 Option#getOrElse
's signature is
getOrElse[B >: A](default: ⇒ B): B
因为它是通用的,所以编译器会尝试找到 B
,使得 opt.getOrElse[B](0L)
具有类型 Int
。所以B
必须满足约束B >: Long
(因为上面签名中的A
是Long
)和B <: Int
(来自return类型)。显然没有这样的B
。 Scala 规范说这一定是一个错误,但没有说是哪个错误,而这里编译器恰好在猜测 B = AnyVal
.
另一种解决方法是指定 opt.getOrElse(0L)
的预期类型:
printInt(opt.getOrElse(0L): Long)
或类型参数:
printInt(opt.getOrElse[Long](0L))