我有以下代码定义类型类。
trait Foo[T] {
def toFoo(x: T): String
}
trait Foos {
def toFoo[T](f: T => String): Foo[T] = new Foo[T] {
def toFoo(x: T): String = f(x)
}
}
object Foo extends Foos {
def toFoo[A: Foo](a: A) = implicitly[Foo[A]].toFoo(a)
implicit def AToFoo: Foo[A] = toFoo { c =>
"A"
}
implicit def BToFoo[T]: Foo[B] = toFoo { c =>
"B"
}
implicit def ListToFoo[T: Foo]: Foo[List[T]] = toFoo { c =>
c.map(toFoo(_)).
}
}
class A
class B extends A
如果我有toFoo(List(new A, new B)
,我现在得到List("A", "A")
而不是List("A", "B")
。对于类型为BtoFoo
的类,如何确保使用AToFoo
方法而不是B
?
答案 0 :(得分:2)
隐式解析是一种纯粹的编译时机制。这里区分子类型的简单方法是在隐含内部匹配。完全删除BToFoo
,而是将A
版本处理两种情况
implicit val AIsFoo : Foo[A] = toFoo {
case b: B => "B"
case a: A => "A"
}
当然,也可以委托部分层次结构的方法。您可以委托A
中的方法,在B
中进行覆盖,并且仍然可以使用类型类对List进行操作,您无法在其中添加方法。
您也可以考虑声明Foo
逆变。