多个备选方案之间的隐式搜索决策

时间:2013-04-16 18:23:11

标签: scala inheritance typeclass implicit

在选择最具体的类型类中是否有任何方法可以使用多个合适的替代方法,而不会产生不同的隐式扩展?它看起来像这样

trait A

trait B extends A

case class C extends B

trait Tester[-T] {def test (t : T) : Boolean}

object Tester{

  def test[T] (t : T)(implicit tester : Tester[T]) = tester.test(t)

  implicit def ATester = new Tester[A] {
    override def test (a : A) = true
  }

  implicit def BTester = new Tester[B] {
    override def test (b : B) = false
  }

}

val c = C()
Tester.test(c)

我希望这会产生错误,因为C在继承层次结构中更接近B而不是A.

2 个答案:

答案 0 :(得分:2)

我将提供一些解释为什么这样做的方式 - 另一个答案有可能的解决方法。

Tester[A]选择Tester[B]的原因与T中的Tester[-T]类型相反。这意味着,Tester[A]要成为Tester[B]的子类,A必须是B的超类 - 就像您的代码示例所示。

因此,当方法test(带有隐含参数)需要Tester[C]的子类型时,替代方案将是Tester[B]Tester[C]的子类)和{{1 (也是Tester[A]的子类,但更具体的一个)。这就是为什么,根据选择最具体类型的规则,Tester[C]被选中。

如果有Tester[A],并且隐式函数返回class D extends C,则不会成为参数Tester[D]的分辨率的一部分。

有关于它的其他信息here

答案 1 :(得分:0)

这似乎有助于

trait Tester[T] {def test (t : T) : Boolean}

object Tester{

  def test[T] (t : T)(implicit tester : Tester[T]) = tester.test(t)

  implicit def ATester[T <: A] = new Tester[T] {
    override def test (a : T) = true
  }

  implicit def BTester[T <: B] = new Tester[T] {
    override def test (b : T) = false
  }

}

有异议吗?