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

non*_*com 20 scala tuples pattern-matching

我有以下类层次结构:

class A
class B extends A
class C extends A
Run Code Online (Sandbox Code Playgroud)

然后,还有另一个类,它接受这些类的实例,并且有一个方法,其中两种模式匹配的情况是这样的:

class D (one: A, two: A) {

  def work {
    (one, two) match {
      case (o, t): (B, B) => ... blablabla
      case (o, t): (B, C) => ... blablabla
      case _ =>
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

但是,当它应该解决匹配而支持第二种情况时(B, C),它会尝试将其解析为(B, B)并提出类强制转换异常C cannot be cast to B.为什么?该怎么办?我怎么能绕过这个?

Bri*_*ith 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
}
Run Code Online (Sandbox Code Playgroud)


Sub*_*oid 8

一如既往,问题是擦除类型.(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 => ...
  }
  ... 
}
Run Code Online (Sandbox Code Playgroud)

它不是那么漂亮,但它不会遇到同样的问题.

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