斯卡拉鸭打字模式匹配

斯卡拉鸭打字模式匹配

我有一个像下面这样的案例类:

// parent class
sealed abstract class Exp()

// the case classes I want to match have compatible constructors
case class A (a : Exp, b : Exp) extends Exp
case class B (a : Exp, b : Exp) extends Exp
case class C (a : Exp, b : Exp) extends Exp

// there are other case classes extending Exp that have incompatible constructor, e.g.
//     case class D (a : Exp) extends Exp
//     case class E () extends Exp
// I don't want to match them

我要搭配:
var n : Exp = ...
n match {
    ...
    case e @ A (a, b) =>
        foo(e, a)
        foo(e, b)
    case e @ B (a, b) =>
        foo(e, a)
        foo(e, b)
    case e @ C (a, b) =>
        foo(e, a)
        foo(e, b)
    ...
}

def foo(e : Exp, abc : Exp) { ... }

有没有一种方法可以将这三个案例合并为一个案例(不向A,B,C添加中间父类)?我无法更改A,B,C或Exp的定义。某种:
var n : Exp = ...
n match {
    ...
    case e @ (A | B | C) (a, b) => // invalid syntax
        foo(e, a)
        foo(e, b)
    ...
}

这显然行不通,而且也不行:
var n : Exp = ...
n match {
    ...
    case e @ (A (a, b) | B (a, b) | C (a, b)) => // type error
        foo(e, a)
        foo(e, b)
    ...
}

最佳答案

尽管以下“解决方案”实际上只是编写已有内容的另一种方法,但是如果您需要在多个地方使用相同的match并希望避免代码重复,则可能会有所帮助。

以下自定义项不适用:

object ExpABC {
    def unapply(e:Exp):Option[(Int, Int)] = e match {
        case A(a, b) => Some(a, b)
        case B(a, b) => Some(a, b)
        case C(a, b) => Some(a, b)
        case _ => None
    }
}

让你写
n match {
    case e @ ExpABC(a, b) =>
        println(e)
        println(a)
        println(b)
}

这样,您根本不需要修改原始类。我不知道一种更好的方法,它不涉及修改A/B/C类,但是我很想学习@ Stackoverflow;)

关于斯卡拉鸭打字模式匹配,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12712922/

10-11 08:42