これは、複数の選択肢間の暗黙の検索決定のフォローアップです。そこからコードを引用します。
trait A
trait B extends A
caseclass 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)
が反変性と特異性に関して暗黙的に探しているときにatester: Tester[A]
が選択される理由を概念的に理解しています。btester: Tester[B]
Tester.test(implicit t: Tester[C])
わかりにくいのは、これを spec の観点から具体的に説明する方法6.26.3 overloading resolution
です。
私の知る限り、仕様では、オーバーロードの解決が必要な識別子または選択 e を 3 つのカテゴリで扱います。
- e は関数適用 e(e1,..., e_m) で使用されます
- e は型適用 e[targs] で使用されます
- それ以外は
さらに、この仕様では、ある選択肢が別の選択肢よりも具体的であることを識別することによって計算された相対的な重みについて説明しています。
まず、代替案をどのカテゴリに適合させるべきかがわかりません。である場合、{ Tester[A], Tester[B] }
(2) の可能性が高いように思われますが、そのルールは --
オーバーロードの解決は、式全体に再度適用されます e[targs]
――またボールを投げ返しているように見えます。また、A と B を比較する方法が仕様のどこに記載されているかを特定することもできません。
同様のもの:同じ質問に対する2ランクの回答では、コードが変更されており、ここにも引用しています:
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 }
}
val c = C()
Tester.test(c)
代替手段は2つのポリモーフィックメソッドだと思います:
{ atester[T <: A]: Tester[T], btester[T<: B]: Tester[T] }
. (1)に該当するようです。しかし、それ以上の理由付けは明確ではありません。