Je fais correspondre des classes de cas et j'aimerais traiter deux cas de la même manière. Quelque chose comme ça:
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"
}
}
Mais quand je fais cela, j'obtiens l'erreur:
(fragment of test.scala):10: error: illegal variable in pattern alternative
case B(sb) | C(sc) => "B"
Je peux le faire fonctionner, je supprime les paramètres de la définition de B et C, mais comment puis-je correspondre aux paramètres?
On dirait que vous ne vous souciez pas des valeurs des paramètres String et que vous voulez traiter B et C de la même façon, alors:
def matcher(l: Foo): String = {
l match {
case A() => "A"
case B(_) | C(_) => "B"
case _ => "default"
}
}
Si vous devez, devez, devez extraire le paramètre et le traiter dans le même bloc de code, vous pouvez:
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"
}
}
Bien que j'estime qu'il serait beaucoup plus propre de prendre cela en compte dans une méthode:
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"
}
}
Je peux voir différentes manières d’atteindre ce que vous recherchez, si vous avez des points communs entre les classes de cas. La première consiste à faire en sorte que les classes de cas étendent un trait qui déclare les points communs, la seconde consiste à utiliser un type de structure qui supprime la nécessité d'étendre vos classes de cas.
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))
}
}
La méthode de type structurel génère un avertissement à propos de l'effacement, mais je ne suis pas sûr de savoir comment le supprimer.
Eh bien, ça n'a pas vraiment de sens, n'est-ce pas? B et C s'excluent mutuellement. Sb ou sc sont donc liés, mais vous ne savez pas lequel. Vous aurez donc besoin d'une logique de sélection supplémentaire pour décider laquelle utiliser (étant donné qu'ils étaient liés à une Option [String], pas un string). Donc, il n'y a rien gagné à ce sujet:
l match {
case A() => "A"
case B(sb) => "B(" + sb + ")"
case C(sc) => "C(" + sc + ")"
case _ => "default"
}
Ou ca:
l match {
case A() => "A"
case _: B => "B"
case _: C => "C"
case _ => "default"
}