以下代码给出了错误。
class Base { }
class Sub extends Base { }
class Writer[-T] {
def write(t: T) { }
}
object AmbImplicits {
implicit object BaseWriter extends Writer[Base]
implicit object SubWriter extends Writer[Sub]
def foo[T](t: T)(implicit ev: Writer[T]) {
println(s"foo $t $ev")
}
def main(args: Array[String]) {
val base = new Base
val sub = new Sub
foo(base)
foo(sub)
}
}
错误:
/Workspace/AmbImplicits.scala:24: error: ambiguous implicit values:
both object SubWriter in object AmbImplicits of type AmbImplicits.SubWriter.type
and object BaseWriter in object AmbImplicits of type AmbImplicits.BaseWriter.type
match expected type Writer[Sub]
foo(sub)
^
在我的实际代码中,显式传递隐式参数并不是那么简单。有没有办法告诉它总是更喜欢SubWriter
而不是BaseWriter
,因为前者更具体?没有像foo(sub)(SubWriter)
那样手动传递它?
答案 0 :(得分:4)
如果由于Base和Sub是Java类型而无法做Shadowlands所建议的,那么你可以通过将它移动到继承链来降低BaseWriter
隐含的优先级:
trait LowPriorityImplicits { implicit object BaseWriter extends Writer[Base] }
object AmbImplicits extends LowPriorityImplicits {
implicit object SubWriter extends Writer[Sub]
def foo[T](t: T)(implicit ev: Writer[T]) {
println(s"foo $t $ev")
}
def main(args: Array[String]) {
val base = new Base
val sub = new Sub
foo(base)
foo(sub)
}
}
答案 1 :(得分:3)
如果你能够,将implicits放在从Base
派生的每个类型的伴随对象中,而不是在foo
方法的对象中:
class Base { }
object Base { implicit object BaseWriter extends Writer[Base] }
class Sub extends Base { }
object Sub { implicit object SubWriter extends Writer[Sub] }
object NotAmbImplicits {
def foo[T](t: T)(implicit ev: Writer[T]) {
println(s"foo $t $ev")
}
def main(args: Array[String]) {
val base = new Base
val sub = new Sub
foo(base)
foo(sub)
}
}
编译器将在伴随对象中查找传递给T
的给定foo
以查看它是否可以使用隐式来源。