2

下面的代码给出了一个错误。

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)
       ^

在我的真实代码中,显式传递隐式参数并不是那么简单。有没有办法告诉它总是更喜欢SubWriterBaseWriter因为前者更具体?无需手动传递它foo(sub)(SubWriter)吗?

4

2 回答 2

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)
  }
}
于 2013-11-14T23:37:26.550 回答
3

如果可以的话,将隐式放在从 派生的每种类型的伴随对象中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查看它是否可以从那里使用隐式。

于 2013-11-14T02:47:21.273 回答