匹配“fallthrough”:为多个案例类执行相同的代码片段?

时间:2013-02-22 08:30:11

标签: scala

我在Scala中有一个匹配不同case类的函数,但在每次匹配时都执行相同的代码。是否存在“落后”的可能性?还是另一种很好的方法来编写代码,而不需要代码重复,也没有定义函数?

symbol match {
            case Times(a,b) => //some code using a and b
            case Plus(a,b)  => //same code as above
            case Div(a,b)   => //again same code as above
}

这个问题与“Match "fallthrough": executing same piece of code for more than one case?”非常相似,区别在于我在与案例类匹配时感到沮丧。

3 个答案:

答案 0 :(得分:4)

不,Scala禁止使用暴虫,因为它们是其他语言中常见的漏洞来源。你有两个三个可能性:

  • 将功能中相同的所有内容分解出来
  • 尝试使用不太具体的匹配,即使用通配符。在您的示例中,这也可能意味着引入一个超类BinaryOperation,它使您可以进行更通用的匹配。请注意,由于案例类继承限制,您必须依赖于使用此超类的字段而不是具有超级案例类。
  • 关注Mirko Stocker编写特定提取器的好建议。

答案 1 :(得分:4)

您可以编写自己的提取器,将三种情况组合在一起并将其转换为元组:

  object BinOp {
    def unapply(op: Op) = op match {
      case Times(a, b) => Some(a, b)
      case Plus(a, b) => Some(a, b)
      case Div(a, b) => Some(a, b)
    }
  }

  symbol match {
    case BinOp(a, b) => 
  }

答案 2 :(得分:1)

我看到了两个可能解决问题的方法

1)unapply

根据M. Stocker的回答,您可以像这样整理数据:

trait Op

trait BinaryOp extends Op {
  def a: Int
  def b: Int
}

object BinaryOp {
  def unapply(op: Op) = op match {
    case x: BinaryOp => Some((x.a, x.b))
    case _ => None
  }
}

case class Times(a: Int, b: Int) extends BinaryOp
case class Plus(a: Int, b: Int) extends BinaryOp
case class Div(a: Int, b: Int) extends BinaryOp

用法:

symbol match {
  case BinaryOp(a, b) => f(a, b)
  case _ => //...
}

2)Product

所有案例类都扩展了Product trait

这允许您进行以下匹配:

symbol match {
  case p: Product if p.productArity == 2 => {
    val a = p.productElement(0) //this has type Any, so a cast may be necessary
    val b = p.productElement(1)
    f(a, b)
  }
}

第二种情况更通用,但它也是类型不安全的。我推荐第一个解决方案。