Неявное forAnyRef
выбрано потому, что оно более конкретно , чем forNumeric
в соответствии с §6.26.3 «Разрешение перегрузки» ссылки Scala.Есть способ уменьшить приоритет, переместив его в черту, которая расширяет Default
, например:
trait LowerPriorityImplicits extends LowestPriorityImplicits {
this: Default.type =>
implicit def forAnyRef[A >: Null] = withValue(null: A)
}
object Default extends LowerPriorityImplicits {
// as before, without forAnyRef
}
Но это только часть уловки, потому что теперь и forAnyRef
, и forNumeric
специфичны друг для друга, и вы получите двусмысленную неявную ошибку.Это почему?Ну, forAnyRef
получает дополнительное очко специфичности, потому что имеет нетривиальное ограничение на A
: A >: Null
.Затем, чтобы добавить нетривиальное ограничение к forNumeric
, вы можете удвоить его в Default
:
implicit def forNumericVal[A <: AnyVal: Numeric] = withValue(implicitly[Numeric[A]].zero)
implicit def forNumericRef[A <: AnyRef: Numeric] = withValue(implicitly[Numeric[A]].zero)
Теперь это дополнительное ограничение делает forNumericVal
и forNumericRef
более конкретными, чемforAnyRef
для типов, где доступно Numeric
.