我已经定义了一个隐式类,它在foo
的所有实例上提供了一个方法Double
。奇怪的是,现在也可以调用这种方法。在Float
实例上,由scalac
2.12.5接受的以下示例显示(使用-Xscript Foo
):
implicit class DoubleOps(value: Double) {
def foo: Double = value
}
val x: Float = 1f
val y = x.foo
如果我尝试用我自己的类型做同样的事情,分别用Float
和Double
替换MyFloat
和MyDouble
,foo
在MyFloat
实例上不可用。
trait MyDouble
object MyDouble {
implicit class MyFloatAsMyDouble(value: MyFloat) extends MyDouble
}
trait MyFloat
implicit class MyDoubleOps(value: MyDouble) {
def foo: MyDouble = value
}
val x: MyFloat = new MyFloat { }
val y = x.foo
$ scalac -Xscript Foo foo.scala
foo.scala:14: error: value foo is not a member of this.MyFloat
val y = x.foo
^
one error found
这符合我对编译器如何使用implicits直接搜索在类型上找不到的成员的理解。但为什么第一个例子仍然有效呢?
我相信这是通过numeric widening实现的weak conformance案例。 (对drop this from the language有一个积极的提议。)