8

次のようなケースクラスがあります。

// 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) { ... }

その3つのケースを1つのケースにマージする方法はありますか(中間の親クラスを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)
    ...
}
4

1 に答える 1

11

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を学びたいと思っています;)

于 2012-10-03T16:53:56.413 に答える