我有以下类层次结构:
class A
class B extends A
class C extends A
然后,还有另一个类,它接受这些类的实例,并且有一个方法,其中有两种模式匹配的例子是这样的:
class D (one: A, two: A) {
def work {
(one, two) match {
case (o, t): (B, B) => ... blablabla
case (o, t): (B, C) => ... blablabla
case _ =>
}
}
}
但是,当它应该解决匹配而支持第二种情况(B, C)
时,它会尝试将其解析为(B, B)
并提出C cannot be cast to B
的类强制转换异常。为什么?该怎么办?我怎么能绕过这个?
答案 0 :(得分:29)
你的语法不太正确(不编译)。
但这有效:
object Matcher extends App {
class A
class B extends A
class C extends A
class D(one: A, two: A) {
def work {
(one, two) match {
case (o: B, t: B) => println("B")
case (o: B, t: C) => println("C")
case _ =>
}
}
}
val d1 = new D(new B, new B)
val d2 = new D(new B, new C)
d1.work
//B
d2.work
//C
}
答案 1 :(得分:7)
问题一如既往地是擦除类型。 (B,C)
是Tuple2[B,C]
的语法糖,在运行时被删除为Tuple2
。 case语句验证(B,C)
是否匹配Tuple2
,但后来无法转换它。
在你的情况下,最简单的解决方案是分别匹配'one'和'two',而不是将它们包装在一个元组中:
one match {
case o : B => two match {
case p : C => ...
case p : B => ...
}
...
}
它不是那么漂亮,但它不会遇到同样的问题。
编辑:实际上,我会选择Brian Smith的解决方案 - 在元组内而不是在外部进行匹配。它以类似的方式避免了这个问题,但看起来更好。
答案 2 :(得分:2)
我让这段代码工作了。
首先,我在你的班级定义中添加了一个案例。
case class A
case class B extends A
case class C extends A
其次,我更改了work
。
class D(one: A, two: A) {
def work {
(one, two) match {
case (o: B, t: B) => println("BB")
case (o: B, t: C) => println("BC")
case (o: C, t: C) => println("CC")
case _ => println("AA")
}
}
}
现在我得到了什么:
new D(B(),B()).work => BB
new D(B(),C()).work => BC
new D(C(),C()).work => CC
new D(A(),B()).work => AA
case
添加了apply和unapply方法。