为什么 Scala 的编译器不能使用继承类型的隐式转换?
Why Scala's compiler is not able to use an implicit conversion of an inherited type?
我目前正在深入研究隐含的主题,并被这个案例困住了:
class A
class B extends A
object A { implicit def b2String(b: B): String = "B" }
object B { implicit def a2String(a: A): String = "A" }
val s: String = new B // This does not compile
我知道这有点极端,但我想了解它。编译器不应该选择 A 的 implicit (b2String) 吗?还是(看起来)它坚持最具体类型的伴生对象 (B)?这是否意味着继承类型的伴随对象隐式不被继承?
提前致谢。
编辑:
如果A的伴随对象被删除,那么它编译并且s的值为"A"。所以编译器能够弄清楚对 A 的隐式有效也对 B 有效。
编辑:
如果我进行以下更改,这也会编译:
class A
class B extends A
object A { implicit def b2String(b: B): Int = 1 }
object B { implicit def a2String(a: A): String = "A" }
val s: String = new B
val i: Int = new B
所以伴随对象隐式是继承的。
它无法编译,因为有两个可用的隐式,并且根据 http://scala-lang.org/files/archive/spec/2.11/06-expressions.html#overloading-resolution 中的规则,它们具有相同的相对权重:b2String
比 a2String
多 1,因为它在派生 class 的伴生对象,并且 a2String
比 b2String
多 1,因为它更具体。
我目前正在深入研究隐含的主题,并被这个案例困住了:
class A
class B extends A
object A { implicit def b2String(b: B): String = "B" }
object B { implicit def a2String(a: A): String = "A" }
val s: String = new B // This does not compile
我知道这有点极端,但我想了解它。编译器不应该选择 A 的 implicit (b2String) 吗?还是(看起来)它坚持最具体类型的伴生对象 (B)?这是否意味着继承类型的伴随对象隐式不被继承?
提前致谢。
编辑: 如果A的伴随对象被删除,那么它编译并且s的值为"A"。所以编译器能够弄清楚对 A 的隐式有效也对 B 有效。
编辑: 如果我进行以下更改,这也会编译:
class A
class B extends A
object A { implicit def b2String(b: B): Int = 1 }
object B { implicit def a2String(a: A): String = "A" }
val s: String = new B
val i: Int = new B
所以伴随对象隐式是继承的。
它无法编译,因为有两个可用的隐式,并且根据 http://scala-lang.org/files/archive/spec/2.11/06-expressions.html#overloading-resolution 中的规则,它们具有相同的相对权重:b2String
比 a2String
多 1,因为它在派生 class 的伴生对象,并且 a2String
比 b2String
多 1,因为它更具体。