別のノードを(経由で)指すことができるノードクラスがありますnext
。そのノードは、さまざまな階層でサブクラス化できます。次に、単一リンクリストのイメージで、これらのさまざまなノードのチェーンを作成できます。次に、そのリスト内の任意のノードから始めて、特定のタイプの最初のノードを検索します。したがって、私はその問題のために型パラメータ化された関数を作成しますcheck
。しかし、正しい一致を見つけることができません。これは、Scalaワークシートから抜粋した完全な出力コードの例です。
class A (i: Int) {
var next: Option[A] = None
def + (a: A) = {
next = Some(a)
a
}
override def toString = super.toString + "[" + i + "]"
}
class B (i: Int) extends A (i)
class C (i: Int) extends B (i)
class D (i: Int) extends B (i)
object test {
val start = (new A(0)) //> start : A = A@e80a59[0]
val test = start + (new A(1)) + (new B(2)) + (new C(3)) + (new D(4)) + (new A(5)) + (new C(6))
//> test : A = C@5d173[6]
def check[T <: B](a: A): Option[B] = {
println("starting search for " + a)
a match {
case t: T =>
println("SUCCESS, found=" + t)
Some(t)
case wrong =>
println("did not find! wrong=" + wrong)
a.next match {
case Some(nxt) =>
println("checking next=" + nxt)
check[T](nxt)
case _ =>
println("SEARCH FAILED")
None
}
}
} //> check: [T <: B](a: A)Option[B]
/* correct - i expect this */
println(check[C](new A(1))) //> starting search for A@1f9dc36[1]
//| did not find! wrong=A@1f9dc36[1]
//| SEARCH FAILED
//| None
/* correct - i expect this */
println(check[D](new A(2))) //> starting search for A@e86da0[2]
//| did not find! wrong=A@e86da0[2]
//| SEARCH FAILED
//| None
/* incorrect - it must fail looking for C */
println(check[C](new B(4))) //> starting search for B@1754ad2[4]
//| SUCCESS, found=B@1754ad2[4]
//| Some(B@1754ad2[4])
println(check[B](start)) //> starting search for A@e80a59[0]
//| did not find! wrong=A@e80a59[0]
//| checking next=A@fe64b9[1]
//| starting search for A@fe64b9[1]
//| did not find! wrong=A@fe64b9[1]
//| checking next=B@186db54[2]
//| starting search for B@186db54[2]
//| SUCCESS, found=B@186db54[2]
//| Some(B@186db54[2])
/* incorrect - it must find C(3) instead */
println(check[C](start)) //> starting search for A@e80a59[0]
//| did not find! wrong=A@e80a59[0]
//| checking next=A@fe64b9[1]
//| starting search for A@fe64b9[1]
//| did not find! wrong=A@fe64b9[1]
//| checking next=B@186db54[2]
//| starting search for B@186db54[2]
//| SUCCESS, found=B@186db54[2]
//| Some(B@186db54[2])
/* incorrect - it must find D(4) instead */
println(check[D](start)) //> starting search for A@e80a59[0]
//| did not find! wrong=A@e80a59[0]
//| checking next=A@fe64b9[1]
//| starting search for A@fe64b9[1]
//| did not find! wrong=A@fe64b9[1]
//| checking next=B@186db54[2]
//| starting search for B@186db54[2]
//| SUCCESS, found=B@186db54[2]
//| Some(B@186db54[2])
質問は次のとおりです。
なぜそのように失敗するのですか?渡されたタイプは無視されます。
どうすれば私が望むものを達成できますか?
更新:アドバイスされているように、私はこの手動の明示的な具体化を行うことによって、ここで「型消去」と呼ばれるものと戦うためにScalaの「マニフェスト」を使用しようとしました。しかし、マニフェストの助けを借りてパターンマッチングを行うことはできません。マニフェストは、私が考えることができる方法で機能しないだけでなく、ネット上で実用的な例を見つけることもできませんでした。