3

我在 Scala 中有一个匹配不同案例类的函数,但在每次匹配时执行相同的代码。有没有“落空”的可能?或者在不重复代码且不定义函数的情况下编写以下代码的其他好方法?

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
}

这也是一个非常相似的问题“匹配“失败”:为多个案例执行同一段代码? ”不同之处在于我对匹配案例类很感兴趣。

4

3 回答 3

4

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

  • 分解出函数中所有相同的东西
  • 尝试使用不太具体的匹配,即使用通配符。在您的示例中,这也可能意味着引入一个超类BinaryOperation,它使您有可能进行更通用的匹配。请注意,由于案例类继承限制,您将不得不依赖使用此超类的字段而不是拥有超案例类。
  • 遵循 Mirko Stocker 关于编写特定提取器的好建议。
于 2013-02-22T08:40:24.003 回答
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) => 
  }
于 2013-02-22T08:55:57.587 回答
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 特征

这允许您执行以下匹配:

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)
  }
}

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

于 2013-02-22T09:44:09.877 回答