2012-08-16 46 views
17

我有下面的类层次结构的元组:斯卡拉 - 模式匹配相关类型

class A 
class B extends A 
class C extends A 

然后,有另一类这需要这些类的实例,有一个方法,其中,2箱子模式匹配有可能是这样的:

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出现。为什么?该怎么办?我怎样才能解决这个问题?

回答

26

你的语法不太对(不编译)。

这工作虽然:

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 
} 
+0

我一直在努力寻找正确的语法......谢谢! – Benoit 2014-02-27 09:58:43

2

我使这个代码工作。
首先我给你的类定义添加了一个case。

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增加了应用和不应用方法。

+0

是的,案例类...但他们有继承错误..我会很高兴,如果他们修复某个时候... – noncom 2012-08-16 12:35:46

+0

我完全和你在一起。 – 2012-08-16 12:46:34

+1

这段代码不会在现代Scala中编译,因为我认为从2.9开始禁止案例继承。 @noncom这不是一个bug,这是由设计 – 2012-08-16 21:51:16

7

的问题,一如既往,被删除的类型。 (B,C)是语法糖Tuple2[B,C],它在运行时擦除到Tuple2。案例陈述验证(B,C)Tuple2匹配,但是未能投射它。

在你的情况,最简单的解决办法是要匹配的“一”和“二”单独,而不是在一个元组包裹其中:

one match { 
    case o : B => two match { 
    case p : C => ... 
    case p : B => ... 
    } 
    ... 
} 

这不是那么漂亮,但它不会遭受同样的问题。

编辑:其实,我会与布赖恩史密斯的解决方案 - 匹配内部元组而不是外部。它以类似的方式避免了这个问题,但看起来更好。