考虑以下情况:
trait Companion {
implicit def str(a: A): String =
s"${this.getClass.getSimpleName}: %d" format a.n
}
class A(val n: Int)
object A extends Companion {}
class B(val x: Int, y: Int) extends A(y)
object B extends Companion {}
现在,编译以下代码将触发不同的隐式错误:
val b = new B(5, 2)
val s: String = b
println(s)
因为对象A和AA都在默认的AA隐式范围内。这显然是有缺陷的:AA类比特征A更“精确”,因此它的隐式范围应该具有更高的优先级。不幸的是,由于对象无法彼此继承,因此无法声明这一点。
所以我的问题是:在不诉诸非默认隐式作用域的情况下,实现此目标的最佳方法是什么?
答案 0 :(得分:1)
现在,编译以下代码将触发不同的隐式错误:
这不是“发散的隐式错误”,它是模棱两可的,implicit ambiguity和implicit divergence是不同的。
关于类型X
的隐含性应转到X
的伴随对象。因此,如果这是A
和String
之间的隐式转换,则应转到A
的伴随对象。但是随后您遇到了.getSimpleName
的问题。
常见方法是为伴随对象(如@MarioGalic advises)参数化父特征:
如果您不想将T
设为类型参数,则可以使其成为类型成员
trait Companion {
type T <: A
implicit def str(a: T): String = s"${this.getClass.getSimpleName}: %d" format a.n
}
class A(val n: Int)
object A extends Companion {
type T = A
}
class B(val x: Int, y: Int) extends A(y)
object B extends Companion {
type T = B
}
此外,您可以尝试覆盖隐式
trait Companion {
implicit def str(a: A): String = s"${this.getClass.getSimpleName}: %d" format a.n
}
class A(val n: Int)
object A extends Companion
class B(val x: Int, y: Int) extends A(y)
object B extends Companion {
override implicit def str(a: A): String = super.str(a)
}
或
trait LowPriorityCompanion {
implicit def str(a: A): String = s"${this.getClass.getSimpleName}: %d" format a.n
}
trait Companion extends LowPriorityCompanion {
override implicit def str(a: A): String = super.str(a)
}
class A(val n: Int)
object A extends LowPriorityCompanion
class B(val x: Int, y: Int) extends A(y)
object B extends Companion
答案 1 :(得分:0)
尝试像这样对参数Companion
进行参数设置:
trait Companion[T <: A] {
implicit def str(a: T): String =
s"${this.getClass.getSimpleName}: %d" format a.n
}
class A(val n: Int)
object A extends Companion[A] {}
class B(val x: Int, y: Int) extends A(y)
object B extends Companion[B] {}
val b = new B(5, 2)
val s: String = b
println(s) // B$: 2