2012-06-28 7 views
7

私は、複数のパラメータの大文字と小文字を区別したクラスとのマッチングに使用するエクストラクタを作成しようとしています。簡略化された例:Scala - extractorは混乱を解消します

case class X(p1: String, p2: Int) 

私は各抽出オブジェクトにp1の固定値を定義し、p2は使用時に定義したいと思います。私は、パターンマッチングに

object A { 
    def apply(p2: Int): X = X("A", p2) 
} 

object B { 
    def apply(p2: Int): X = X("B", p2) 
} 

... 

:メソッドを適用すると 例(A、B、等がケースクラスおよびサブクラスXことができない、と私はまた、ケースとしてX()を使用したいです)彼らはこのように一致したいと思います:

X("A", 2) match { 
    case A(2) => true // <- should match: p1="A" and p2=2 
    case A(_) => true // <- should match: p1="A" and p2=_ 
    case X("A", _) => true // <- should match: p1="A" and p2=_ 
    case A(1) => false // <- should not match 
    case B(2) => false // <- should not match: p1="B" and p2=2 
} 

私はなどAB、中unapply方法を定義する必要があります知っているが、私は署名とロジックがどうあるべきかを徹底的に困惑している:

object A { 
    def unapply(x: ???): Option[???] = { 
    ??? 
    } 
} 

助けてください。

答えて

14

unapplyは、Anyを取り、抽出したいものをOption返します。あなたのケースでは、これは次のようになります。

正直に言うと、あなたが思い付いた例は ABずに書き換えることができますが
scala> case class X(p1: String, p2: Int) 
defined class X 

scala> object A { 
    | def unapply(target: Any): Option[Int] = 
    |  PartialFunction.condOpt(target) { 
    |  case X("A", p2) => p2 
    |  } 
    | } 
defined module A 

scala> val A(x) = X("A", 1) 
x: Int = 1 

scala> val A(x) = X("B", 1) 
scala.MatchError: X(B,1) (of class X) 
... 

:最初の例で

X("A",2) match { 
    case X("A", 2) => true 
    case X("A", 1) => false 
    case X("A", _) => true 
    case X("B", 2) => false 
} 
+5

、私はしばしば '部分写像を使用しています。 '' PartialFunction.condOpt(target){case X( "A"、p2)=> Some(p2)} 'のようなデフォルトのケースを書くのを避けるためにcondOpt'を使います。 – Nicolas

+0

私はそれを知らなかった。驚くばかり! –

+0

だから簡単!ありがとう!ところで、私はこの例がそのように書くことができることを知っていますが、この例は単純化されています。抽出器の主な目的は、容易に想起されないパラメータの組み合わせをカプセル化することです。 – 7zark7