Scala如何将Int转换为Double?

时间:2018-03-08 00:02:36

标签: scala coercion

val d: Double = 42

当我尝试通过intellij找到隐式转换时,没有任何有趣的东西出现。此外,Int不是Double的子类型。那么Scala是如何做到的呢?

1 个答案:

答案 0 :(得分:12)

长话短说:这不是对某些伴侣对象的普通隐式转换,数值类型得到了特殊处理。

如果我们在此脚本上运行scala -print

val d: Double = 42

我们获得:

package <empty> {
  object Main extends Object {
    def main(args: Array[String]): Unit = {
      new <$anon: Object>();
      ()
    };
    def <init>(): Main.type = {
      Main.super.<init>();
      ()
    }
  };
  final class anon$1 extends Object {
    private[this] val d: Double = _;
    <stable> <accessor> private def d(): Double = anon$1.this.d;
    def <init>(): <$anon: Object> = {
      anon$1.super.<init>();
      anon$1.this.d = 42.0;
      ()
    }
  }
}

在desugared代码中,我们看到了双字面42.0,但没有任何转换的调用 函数(例如来自Predef)。因此,必须不进行从IntDouble的转换 在运行时,但在编译的早期阶段。

section 3.5.3 of the specification 告诉我们,由于弱一致性关系Int的传递性,Double <:w

Int <:w Long <:w Float <:w Double

此外,Section 6.26.1 (Value Conversions) 告诉我们,如果e类型的表达式T出现在表达式为pt的位置,则适用数字扩展的规则 类型T是预期的,pt弱于e = 42。在这种情况下,我们可以使用

来应用规则
  • 表达式T = Int
  • 表达式类型pt = Double
  • 预期类型42

因此,使用42.0toDouble转换为toDouble。因为它是一个可以在编译时处理的常量, 我们在desugared代码中看不到val d: Double = (new scala.util.Random).nextInt(42) 。但是,如果我们用非常数来减少类似的程序 值

package <empty> {
  object Main extends Object {
    def main(args: Array[String]): Unit = {
      new <$anon: Object>();
      ()
    };
    def <init>(): Main.type = {
      Main.super.<init>();
      ()
    }
  };
  final class anon$1 extends Object {
    private[this] val d: Double = _;
    <stable> <accessor> private def d(): Double = anon$1.this.d;
    def <init>(): <$anon: Object> = {
      anon$1.super.<init>();
      anon$1.this.d = new scala.util.Random().nextInt(42).toDouble();
      ()
    }
  }
}

我们获得:

toDouble

并且<!DOCTYPE html> <html lang="en"> <head> <meta content="width=device-width, initial-scale=1.0" name="viewport"></meta> <meta content="text/html; charset=utf-8" http-equiv="Content-Type"></meta> <script src="https://code.jquery.com/jquery-1.12.4.js"></script> <link href="resource/css/main.css" rel="stylesheet"></link> <title>My App</title> </head> <body> <form action="${pageContext.request.contextPath}/uploadServlet" method="post" enctype="multipart/form-data"> <input type="text" name="description" /> <input type="file" name="file" /> <input type="submit" name="submit"/> </form> <button id="processData" type="button" class="btn btn-primary">ProcessData</button> <br></br> <br></br> <script src="js/mainJs.js"></script> </body> </html> 符合规定。