Scala:在模糊隐式转换的情况下选择哪一个?

时间:2015-09-02 05:26:13

标签: scala implicit-conversion implicit

为什么在Scala中编译以下(玩具)示例没有任何问题,用于决定选择哪个隐式转换的规则是什么?

object test1 {
  class MyInt(val v: Int) {
    def +(other: MyInt) = new MyInt(v + other.v)
    override def toString = v.toString
  }
  class MyIntMod10(vparam: Int) {
    val v = vparam % 10;
    def +(other: MyIntMod10) = new MyIntMod10(v + other.v)
    override def toString = v.toString
  }

  val a = new MyInt(7);                           //> a  : test1.MyInt = 7
  val b = new MyIntMod10(7);                      //> b  : test1.MyIntMod10 = 7
  implicit def toIntMod10(x: MyInt) = new MyIntMod10(x.v)
                                                  //> toIntMod10: (a: test1.MyInt)test1.MyIntMod10
  val c1 = a + b                                  //> c1  : test1.MyIntMod10 = 4
  val c2 = b + a                                  //> c2  : test1.MyIntMod10 = 4

  implicit def toInt(x: MyIntMod10) = new MyInt(x.v) //> toInt: (b: test1.MyIntMod10)test1.MyInt
  val c3 = a + b                                  //> c3  : test1.MyInt = 14
  val c4 = b + a                                  //> c4  : test1.MyIntMod10 = 4
}

由于含糊不清,我预计最后两行会产生编译时错误,但他们不会这样做。 (据我所知,c1和c3的值不同,直接显示了计算c3时的模糊性!如果我错了,请纠正我。)

我知道在当前版本的Scala中,编译器会解决一些模糊的隐式调用,但是我无法看到给定的示例代码是如何处理这些特殊情况之一的!

1 个答案:

答案 0 :(得分:1)

如果行设置为c1c3,则调用的+方法是MyInt上定义的方法。在这些情况下,编译器首先尝试将参数转换为+方法(b)为MyInt。同样,对于c2c4,调用的+方法是MyIntMod10上定义的方法,因此编译器会将a转换为MyIntMod10 }}。

这适用于c2c3c4,其中有适当的隐含可用。

对于c1的情况,没有隐含(此时)将b转换为MyInt,因此它会寻找转换a的方法使用+方法可以将MyIntMod10作为参数 - 并因此找到隐式转换为MyIntMod10以应用于a,将其转换为{ {1}}正如您所观察到的那样。