当转换发生在隐式类声明中时,编译器无法选择正确的隐式转换方法。在下面的示例中,我有一个Foo[T]
类和一个隐式Helper
类,它接受Foo
并提供一个print
方法。该 print 方法调用show
,它本身就是一个隐式转换提供的方法 on Foo
。
问题是提供了两种可能的转换show
:一种转换Foo[T]
为 a Bar[T]
,另一种转换Foo[Array[T]]
为 a BarArray[T]
。这个想法是,当我们有一个Foo
包含数组的 a 时,我们希望应用更具体的BarArray
转换。据我了解,编译器首先选择具有最具体类型的转换。
这在正常上下文中有效,如下例所示,但print
在隐式Helper
类中的方法的上下文中中断。在那里,show
调用了相同的方法,因此我希望应该应用相同的转换。但是,在这种情况下,编译器总是选择Bar
转换,即使它有Foo[Array[T]]
并且应该选择BarArray
转换。
出了什么问题?
最小的失败代码示例:
package scratch
import scala.language.implicitConversions
class Foo[T](val value: T) {}
object Foo {
implicit def fooToBar[T](foo: Foo[T]): Bar[T] = {
new Bar(foo.value)
}
implicit def fooArrayToBarArray[T](foo: Foo[Array[T]]): BarArray[T] = {
new BarArray(foo.value)
}
}
class Bar[T](val value: T) {
def show(): String = {
s"Bar($value)"
}
}
class BarArray[T](val value: Array[T]) {
def show(): String = {
value.map(v => s"Bar($v)").mkString(", ")
}
}
object Scratch extends App {
implicit class Helper[T](foo: Foo[T]) {
def print(): Unit = {
println(foo.show())
}
}
val foo0 = new Foo(123)
val foo1 = new Foo(Array(123, 456))
// conversions to Bar and BarArray work correctly here
println(foo0.show()) // Bar(123)
println(foo1.show()) // Bar(123), Bar(456)
// conversions called from within the implicit Helper class
// always choose the Bar conversion
foo0.print // Bar(123)
foo1.print // Bar([I@xxxxxxxx) <- should be Bar(123), Bar(456)
}
版本:
- 斯卡拉 2.12.10
- SBT 1.4.3
- JDK 1.8.0_241