我有一个节点类,它可以指向另一个节点(通过next
)。该节点可以在不同的层次结构中进行子类化。然后,我可以在单链表的图像中拥有这些不同节点的链。然后,从该列表中的任意节点开始,我想搜索特定类型的第一个节点。因此,我为此创建了一个类型参数化的函数check
。但它未能找到正确的匹配。下面是完整的输出代码示例,取自 Scala Worksheet:
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“清单”来与这里所谓的“类型擦除”作斗争,方法是执行此手动显式具体化。但是,我无法在清单的帮助下进行模式匹配 - 它根本无法以我能想到的任何方式使用它,我也无法在网上找到任何工作示例。