隐式转换多个级别,为什么int要自动工作?

时间:2015-01-31 13:21:58

标签: scala

我一直认为在scala中无法实现多级隐式转换(除非你定义了视图边界:http://docs.scala-lang.org/tutorials/FAQ/context-and-view-bounds.html

但似乎类型系统存在缺陷或不一致。 以下示例(改编自How can I chain implicits in Scala?

class A(val n: Double){
  def total = n + 10
}

object T1{
  implicit def toA(n: Double): A = new A(n)
  val i : Int = 5
  println(i.total) //Why does this work?
  println(5.2.total)
}

我真的不明白为什么隐式转换来自Int - >双 - >一件作品。有人可以解释原因吗?感谢

2 个答案:

答案 0 :(得分:7)

它通过一种不同的机制发生,这种机制对于数字类型是唯一的,称为数字扩展

SLS 6.26.1 Value Conversions说:

  

以下五个隐式转换可以应用于表达式 e ,它具有一些值类型 T ,并且使用某些预期类型 pt <进行类型检查/ em>的

     

静态重载决议

     

输入实例化

     

数字扩展

     

Numeric Literal Narrowing

     

价值放弃

     

查看申请

     

动态会员选择

(好的,超过五个......不知道为什么:)

感兴趣的是数字扩展:

  

如果 e 的原始数字类型weakly conforms为预期类型,则使用其中一种数字转换方法toShort {{}}将其扩展为预期类型1}},toChartoInttoLongtoFloat已定义here

3.5.16 Weak Conformance

  

在某些情况下,Scala使用更一般的一致性关系。类型S弱类型符合类型T,写入S&lt;:wT,如果S&lt; T或S和T都是原始数字类型,并且S在以下顺序中在T之前。

toDouble

所以Byte <:w Short Short <:w Int Char <:w Int Int <:w Long Long <:w Float Float <:w Double 变为println(i.total),因为println(i.total.toFloat)

Java(以及C#和许多其他语言)都有数字扩展,Scala决定保留它。

请注意,反向不起作用:Int <:w <: Long <: Float无法通过这种方式隐式转换为Float,因为幅度可能会丢失;它不是&#34;扩大&#34;。

您可以添加Int并在发生这种情况时收到警告。

答案 1 :(得分:1)

正如Gabor已经评论过的,这是due to numeric widening。如果您使用-print选项投放,则会看到.toDouble附加了i,然后允许其使用toA implicit。您可以使用scalac运行warn-numeric-widen,这至少会为您提供以下内容:

<console>:14: warning: implicit numeric widening
     println(i.total) //Why does this work?
             ^