我一直认为在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 - >双 - >一件作品。有人可以解释原因吗?感谢
答案 0 :(得分:7)
它通过一种不同的机制发生,这种机制对于数字类型是唯一的,称为数字扩展。
SLS 6.26.1 Value Conversions说:
以下五个隐式转换可以应用于表达式 e ,它具有一些值类型 T ,并且使用某些预期类型 pt <进行类型检查/ em>的
静态重载决议
输入实例化
数字扩展
Numeric Literal Narrowing
价值放弃
查看申请
动态会员选择
(好的,超过五个......不知道为什么:)
感兴趣的是数字扩展:
如果 e 的原始数字类型weakly conforms为预期类型,则使用其中一种数字转换方法
toShort
{{}}将其扩展为预期类型1}},toChar
,toInt
,toLong
,toFloat
已定义here。
在某些情况下,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?
^