いくつかのケースクラスに対してマッチングを行っていますが、2つのケースを同じ方法で処理したいと思います。このようなもの:
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"
}
}
ケースクラス間に共通性がある場合、あなたが望んでいることを達成するために私が見ることができるいくつかの方法があります。 1つ目は、ケースクラスで共通性を宣言する特性を拡張することであり、2つ目は、ケースクラスを拡張する必要のない構造型を使用することです。
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))
}
}
構造型のメソッドは、消去についての警告を生成しますが、現時点では消去する方法がわかりません。
まあ、それは本当に意味をなさない、そうですか? BとCは相互に排他的であるため、sbまたはscのいずれかがバインドされますが、どちらを使用するかはわからないので、どちらを使用するかを決定するためにさらに選択ロジックが必要になります文字列)。したがって、これに関しては何も得られません。
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"
}