在scala中匹配多个case类
我正在对一些案例类进行匹配,并希望以相同的方式处理两个案例。 像这样的东西:
abstract class Foo case class A extends Foo case class B(s:String) extends Foo case class C(s:String) extends Foo def matcher(l: Foo): String = { l match { case A() => "A" case B(sb) | C(sc) => "B" case _ => "default" } }
但是当我这样做,我得到的错误:
(fragment of test.scala):10: error: illegal variable in pattern alternative case B(sb) | C(sc) => "B"
我可以得到它的工作我从B和C的定义中删除参数,但我怎样才能与参数相匹配?
看起来你不关心string参数的值,并且想把B和C一样对待,所以:
def matcher(l: Foo): String = { l match { case A() => "A" case B(_) | C(_) => "B" case _ => "default" } }
如果必须,必须提取参数并将它们对待在同一个代码块中,您可以:
def matcher(l: Foo): String = { l match { case A() => "A" case bOrC @ (B(_) | C(_)) => { val s = bOrC.asInstanceOf[{def s: String}].s // ugly, ugly "B(" + s + ")" } case _ => "default" } }
虽然我觉得把这个分解成一个方法会更清晰:
def doB(s: String) = { "B(" + s + ")" } def matcher(l: Foo): String = { l match { case A() => "A" case B(s) => doB(s) case C(s) => doB(s) case _ => "default" } }
如果在案例类别之间有一些共同点,我可以通过几种方法来实现您的目标。 首先是让case类扩展一个声明共同性的特征,其次是使用一个结构types来消除扩展你的case类的需要。
object MuliCase { abstract class Foo case object A extends Foo trait SupportsS {val s: String} type Stype = Foo {val s: String} case class B(s:String) extends Foo case class C(s:String) extends Foo case class D(s:String) extends Foo with SupportsS case class E(s:String) extends Foo with SupportsS def matcher1(l: Foo): String = { l match { case A => "A" case s: Stype => println(ss); "B" case _ => "default" } } def matcher2(l: Foo): String = { l match { case A => "A" case s: SupportsS => println(ss); "B" case _ => "default" } } def main(args: Array[String]) { val a = A val b = B("B's s value") val c = C("C's s value") println(matcher1(a)) println(matcher1(b)) println(matcher1(c)) val d = D("D's s value") val e = E("E's s value") println(matcher2(d)) println(matcher2(e)) } }
结构types方法产生一个关于擦除的警告,目前我不知道如何消除。
那么,这真的没有道理,是吗? B和C是互斥的,所以无论是sb还是sc都是绑定的,但是你不知道哪一个,所以你需要更多的select逻辑来决定使用哪一个(假设它们绑定了一个Option [String],而不是一个string)。 所以没有什么比这更好的了:
l match { case A() => "A" case B(sb) => "B(" + sb + ")" case C(sc) => "C(" + sc + ")" case _ => "default" }
或这个:
l match { case A() => "A" case _: B => "B" case _: C => "C" case _ => "default" }