2012-06-28 23 views
7

我正在嘗試編寫一個提取器用於匹配多個參數的案例類。簡化的例子:斯卡拉 - 提取器無應用混淆

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

我想每個提取對象來定義爲P1的固定值,P2是上的用途。 (A,B等不能的情況下,類別和亞類X,我也想用X(),爲殼體) 實施例與應用方法:

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

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

... 

對於模式匹配,我希望他們配合這樣的:

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。在你的情況,這將是:

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

不過說實話,你來了的例子可以不AB改寫:

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'以避免寫入一個未應用的缺省情況(這裏:'PartialFunction.condOpt(target){case X(「A」,p2)=> Some(p2)}'';您也可以導入'PartialFunction._')。 – Nicolas

+0

我不知道。真棒! –

+0

太簡單了!謝謝!順便說一句,我知道這個例子可以這樣寫,但這個例子是簡化的。提取器的主要目的是封裝不易被召回的參數組合。 – 7zark7