如何匹配多个案例类并提取相同的(-named)参数?

时间:2014-09-21 07:08:54

标签: scala inheritance pattern-matching case-class extractor

考虑以下设计的实施一元&的例子。实数表达式的二元运算。

abstract class DoubleE
case class Negate(x: DoubleE) extends DoubleE
case class Reciprocal(x: DoubleE) extends DoubleE
case class Mult(lhs: DoubleE, rhs: DoubleE) extends DoubleE
case class Div(lhs: DoubleE, rhs: DoubleE) extends DoubleE
...
// a lot more binary operations

现在,我想做类似的事情:

(e: DoubleE) match {
   case DoubleEUnary(x) => ... // use x ...
   case DoubleEBinary(a, b) => ... // use a and b ...
}

有时我甚至想参考匹配的类型;例如

e match {
  case DoubeEBinary(a, b) => DoubleEBinary(b, a)
  ...
}

我尝试过的一些失败的尝试:

  • abstract case class DoubleEBinary(a: DoubleE, b: DoubleE) +从中扩展,但不允许这样做:错误: ...禁止使用case-to-case继承。要克服此限制,请使用提取器在非叶节点上进行模式匹配
  • 上述错误暗示:

    abstract case class DoubleEBinary(a: DoubleE, b: DoubleE)
        def unapply(binOp: DoubleEBinary) = Some((a, b))
    

    哪个不起作用:错误:找不到:值DoubleEBinary

  • 尝试使用案例别名
    • case binOp @ (Mult(a, b) | Div(a, b) | ...) => ...
    • case binOp(a, b) @ (Mult(_, _) | Div(_, _) | ...) => ...
    • case (binOp @ Mult(a, b)) | (binOp @ Div(a, b)) => ...

我没有尝试过的一件事就是使用嵌套函数进行重载,这看起来像是一种矫枉过正......

在与上述类似的场景中,是否有一种匹配多个案例类的好方法?

注意:在继承中添加其他方法,类和特征是可以的。

2 个答案:

答案 0 :(得分:2)

错误消息中的提示是:

scala> object Binary { def unapply(e: Mult) = Mult.unapply(e) ; def unapply(e: Div) = Div.unapply(e) }
defined object Binary

scala> Div(null,null) match { case Binary(a,b) => (a,b) }
res3: (DoubleE, DoubleE) = (null,null)

抱歉,即将在这里睡觉,最好用unapply(b: Binary)DoubleE.unapply(d: DoubleE)来表示匹配的子类型。

答案 1 :(得分:0)

从 Scala 2.13 开始,可能很早之前,您可以完全按照您输入的内容进行操作