Scala类型推断和隐式转换

时间:2019-03-21 05:27:09

标签: scala type-inference implicit-conversion

以下代码有效:

scala> import scala.language.implicitConversions
import scala.language.implicitConversions

scala> implicit val longToInt = (l: Long) => l.toInt
longToInt: Long => Int = $$Lambda$1821/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

2 个答案:

答案 0 :(得分:1)

撰写时

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(因为上述签名中的ALong)和B <: Int(来自返回类型)。显然,没有这样的B。 Scala规范说这肯定是一个错误,但没有说明哪个,在这里编译器在猜测B = AnyVal之后碰巧报告了它。

另一种解决方法是为opt.getOrElse(0L)指定所需的类型:

printInt(opt.getOrElse(0L): Long)

或类型参数:

printInt(opt.getOrElse[Long](0L))

答案 1 :(得分:0)

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)