在scala中从Int到Double的隐式转换不起作用

Voi*_*BzY 11 scala implicit-conversion scalac

我已经编写了一些隐式代码,如下所示,我想知道为什么i2d不调用函数隐式对话.

object Test {
  implicit def i2d(x: Int): Double = {
    println("foo")
    x.toDouble
  }

  implicit def d2i(x: Double): Int = {
    x.toInt
  }

  val x: Int = 10
  val y: Double = x
  val z: Int = 3.5
}
Run Code Online (Sandbox Code Playgroud)

输出scalac -Xprint:typer Test.scala

// Test.scala
[[syntax trees at end of typer]] 
package <empty> {
  object Test extends scala.AnyRef {
    def <init>(): Test.type = {
      Test.super.<init>();
      ()
    };
    implicit def i2d(x: Int): Double = {
      scala.this.Predef.println("foo");
      x.toDouble
    };
    implicit def d2i(x: Double): Int = x.toInt;
    private[this] val x: Int = 10;
    <stable> <accessor> def x: Int = Test.this.x;
    private[this] val y: Double = Test.this.x.toDouble;
    <stable> <accessor> def y: Double = Test.this.y;
    private[this] val z: Int = Test.this.d2i(3.5);
    <stable> <accessor> def z: Int = Test.this.z
  }
}
Run Code Online (Sandbox Code Playgroud)

眼镜

  • scalac版本是2.11.8.

Ale*_*lec 13

这比我想象的要多得多.

起初,我认为这是因为Scala如何解决隐含问题.不知何故,我认为这隐含在Int.scala优先次序中.优先级规则通常是直观的,但对于这样的边缘情况,我们参考6.26.3重载分辨率.让我感到困惑的是那个电话int2double不在那里 - 它已经被内联了.toDouble!!

挖了一点之后,似乎有一个关于值类型的边缘情况适用于转换IntDouble.称为弱一致性的东西决定了我们如何转换Byte -> Short -> Int -> Long -> Float -> Double.所以,总而言之,我认为你不能否决这种内置转换......

此转换称为数字扩展

数字扩展

如果e具有弱符合预期类型一个原始号码类型,它被加宽使用的数字转换方法之一的预期的类型toShort,toChar, toInt,toLong,toFloat,toDouble...

编辑

此外,如果有人想知道为什么这是一件事,来自Martin Odersky(这是一个旧的链接 - 不要相信这里所说的一般),如果我们没有这些额外的特殊问题,我们会遇到共同的问题转换:

scala-hypothetical> val x = List(1, 2.0) 
x: List[AnyVal]
Run Code Online (Sandbox Code Playgroud)

不是很直观......