Scala - 模式匹配相关类型的元组

时间:2012-08-16 12:13:59

标签: scala pattern-matching tuples

我有以下类层次结构:

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的类强制​​转换异常。为什么?该怎么办?我怎么能绕过这个?

3 个答案:

答案 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方法。