2

我有这两个隐式

trait A[T] {
  val name: String
}

trait B

object A {
  implicit def product[T <: Product] = new A[T] {
    override val name: String = "product"
  }

  implicit def childOfB[T <: Product with B] = new A[T] {
    override val name: String = "child of B"
  }
}

如果我尝试找到A[C]where Cis的隐式实例

case class C() extends B

childOfB将被选中。

我知道这是合乎逻辑的,但为什么会发生这种情况?我在任何地方都找不到它的记录。

4

3 回答 3

4

Scala 语言规范说:

如果有几个符合条件的参数与隐式参数的类型匹配,则将使用静态重载解析规则选择最具体的参数。

重载分辨率具有一个符号比另一个符号更具体的概念。精确的,特异性的一般定义非常复杂(如您在上面链接的规范中所见),但在您的情况下,它归结为childOfB严格涵盖了所涵盖的类型的子集,product因此更具体

于 2018-08-12T08:05:47.357 回答
2

为了扩展 @ghik 的答案,来自Programmming in Scala

更准确地说,如果以下情况之一适用,则一种隐式转换比另一种更具体:

  • 前者的论点是后者的子类型
  • 两种转换都是方法,前者的封闭类扩展了后者的封闭类

我的猜测是,引用中的“参数”也指类型参数,正如所建议的那样

object A {
  implicit def A2Z[T <: A] = new Z[T] {println("A")}
  implicit def B2Z[T <: B] = new Z[T] {println("B")}
}

trait A
trait B extends A

trait Z[T]

def aMethod[T <: A](implicit o: Z[T]) = ()

implicit val a: A = new A {}

aMethod // prints B even though we started with an A
于 2018-08-12T09:48:31.480 回答
2

规格

如果有几个符合条件的参数与隐式参数的类型匹配,则将使用静态重载解析规则选择最具体的参数。

于 2018-08-12T08:04:08.043 回答