为了理解这个问题,让我们看一下-Xprint:typer
显示的内容:
在第一种情况下,您将 a 传递给testTuple: (String, Int) = (String,2)
期望: 的方法testTupleType: (x: (String, Double))Unit
,但 Scala 没有从Tuple2[String, Int]
to的隐式转换Tuple2[String, Double]
:
val t = Tuple2[String, Int]("a", 2)
val a: (String, Double) = t
<console>:8: error: type mismatch;
found : (String, Int)
required: (String, Double)
val a: (String, Double) = t
^
请记住,(String, Int) 只是调用 Tuple2.apply 的编译器的语法糖。
那么为什么秒片段有效?因为 Scala 将其脱糖到Tuple2[String, Double]
:
private[this] val res1: Unit = testTupleType(scala.Tuple2.apply[String, Double]("String", x.toDouble));
<stable> <accessor> def res1: Unit = res1
总而言之,在第一种情况下,您已经有一个 Tuple2[String, Int] 并且 Scala 没有将其隐式转换为 Tuple2[String, Double],但您可以自己制作:
implicit def tsi2tdi(t: Tuple2[String, Int]): Tuple2[String, Double] = (t._1, t._2.toDouble)
在第二种情况下,它会看到您有一个 String 和一个 Int ,您需要将它们转换为Tuple2[String, Double]
.
更新
不,它不是由apply
方法调用的,而是由编译器调用的。在编译 Scala 时会执行不同的分析阶段,其中之一称为typer
. 当scalac
看到然后你Int
在代码中有一个,但是你想要得到的是一个Double
值,它知道,根据senia提到的弱一致性规则,它可以通过调用方法来获取一个Double
from 。从 Scala 的角度来看,这不是隐式转换。如果你还记得原始转换是在 C 和 Java 中,早在 Scala 之前Int
toDouble