11

場合によっては型クラスを使用して API を設計していますが、暗黙的な解決で問題が発生しました。以下に示すように、タイプ A の暗黙のオブジェクトが存在するが、タイプのオブジェクトがB extends Aメソッドに渡される場合、暗黙のオブジェクトを見つけることができません。これを機能させる方法はありますか、または呼び出し元は暗黙のオブジェクトを各サブクラスのスコープに入れる必要がありますか?

次に例を示します。

class A
class B extends A

class T[+X]

object T {
  implicit object TA extends T[A]
}

def call[X:T](x:X) = println(x)

// compiles
call(new A)
// doesn't compile
call(new B)

var a = new A
// compiles
call(a)

a = new B
// compiles
call(a)

val b = new B
// doesn't compile
call(b)

これは、次の出力でコンパイルに失敗します。

/private/tmp/tc.scala:16: エラー: タイプ this.T[this.B] の証拠パラメーターの暗黙的な値が見つかりませんでした
コール(新B)
    ^
/private/tmp/tc.scala:28: エラー: タイプ this.T[this.B] の証拠パラメーターの暗黙的な値が見つかりませんでした
コール(b)
4

3 に答える 3

8

この呼び出しcall(new B)call[B](new B)(tB)、tb が T[B] 型またはそのサブクラスであることを意味します。(タイプ T の引数を期待するメソッドは、T または T のサブクラスのみを期待できます。たとえば、def foo(s: String)タイプ の引数で呼び出すことはできませんAny)。T[A] は T[B] のサブタイプではありません

修正するには、 T を defined に変更しますT[-X]。これは、コンパイラが T[A] を T[B] のサブタイプと見なすことを意味します。

于 2010-10-06T12:09:45.433 に答える
4

以下はうまくいきます:

scala> def call[X](x: X)(implicit evidence: T[X]<:<T[X])  = println(x)
call: [X](x: X)(implicit evidence: <:<[T[X],T[X]])Unit

scala> call(new A)
line0$object$$iw$$iw$A@1d869b2

scala> call(new B)
line2$object$$iw$$iw$B@b3a5d1

scala> val b = new B
b: B = B@30e4a7

scala> call(b)
line2$object$$iw$$iw$B@30e4a7

def call[X:T](x:X) = println(x)あなたの場合、は として扱われるため、コンパイルは失敗しますcall: [X](x: X)(implicit evidence$1: T[X])Unit。サブタイプを渡すために、一般化された型制約を使用できます。

于 2010-10-06T07:01:10.733 に答える
2

これを試して:

object T {
  implicit def TA[X <: A] = new T[X]
}

import T._

または単に:

implicit def TA[X <: A] = new T[X]
于 2010-10-06T06:58:36.727 に答える