我正在对一些案例类进行匹配,并希望以相同的方式处理其中两个案例。像这样:
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的定义中删除了参数,但我怎样才能与params匹配?
答案 0 :(得分:141)
看起来你不关心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"
}
}
答案 1 :(得分:9)
如果你在案例类之间有一些共性,我可以通过几种方式来实现你所追求的目标。第一个是让case类扩展一个声明共性的特性,第二个是使用一个结构类型,它不需要扩展你的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(s.s); "B"
case _ => "default"
}
}
def matcher2(l: Foo): String = {
l match {
case A => "A"
case s: SupportsS => println(s.s); "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))
}
}
结构类型方法会产生关于擦除的警告,目前我不确定如何消除。
答案 2 :(得分:6)
嗯,它没有意义,是吗? B和C是互斥的,所以sb或sc都要绑定,但是你不知道哪个,所以你需要进一步的选择逻辑来决定使用哪个(假设它们被绑定到Option [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"
}