2012-06-28 28 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