Приоритет ограничения типа Scala в неявном разрешении
У меня есть эти 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]
где C
является
case class C() extends B
childOfB
будет выбран.
Я знаю, что это логично, но почему это происходит? Я не могу найти это нигде документально.
3 ответа
Спецификация языка Scala гласит:
Если имеется несколько подходящих аргументов, которые соответствуют типу неявного параметра, наиболее определенный из них будет выбран с использованием правил разрешения статической перегрузки.
Разрешение перегрузки имеет представление о том, что один символ более специфичен, чем другой. Точное, общее определение специфичности довольно сложно (как вы можете видеть в приведенной выше спецификации), но в вашем случае оно сводится к тому, что childOfB
охватывает строго подмножество типов, охватываемых product
и, следовательно, более конкретно.
Спецификация говорит
Если имеется несколько подходящих аргументов, которые соответствуют типу неявного параметра, наиболее определенный из них будет выбран с использованием правил разрешения статической перегрузки.
Чтобы расширить ответ @ghik, из Программирование в 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