scala - paso - modelo de clase uml
Coincide con mĂșltiples clases de casos en scala (3)
Bueno, realmente no tiene sentido, ¿verdad? B y C son mutuamente excluyentes, de modo que sb o sc quedan vinculados, pero no se sabe cuál, por lo que necesitaría más lógica de selección para decidir cuál usar (dado que estaban vinculados a una Opción [String], no una cuerda). Así que no hay nada ganado con esto:
l match {
case A() => "A"
case B(sb) => "B(" + sb + ")"
case C(sc) => "C(" + sc + ")"
case _ => "default"
}
O esto:
l match {
case A() => "A"
case _: B => "B"
case _: C => "C"
case _ => "default"
}
Estoy haciendo coincidir con algunas clases de casos y me gustaría manejar dos de los casos de la misma manera. Algo como esto:
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"
}
}
Pero cuando hago esto obtengo el error:
(fragment of test.scala):10: error: illegal variable in pattern alternative
case B(sb) | C(sc) => "B"
Puedo hacerlo funcionar. Elimino los parámetros de la definición de B y C, pero ¿cómo puedo unirme a los params?
Hay un par de formas en que puedo ver para lograr lo que busca, si tiene algo en común entre las clases de casos. El primero es hacer que las clases de caso extiendan un rasgo que declara lo común, el segundo es usar un tipo estructural que elimine la necesidad de extender sus clases de casos.
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))
}
}
El método de tipo estructural genera una advertencia sobre el borrado que, en este momento, no estoy seguro de cómo eliminarlo.
Parece que no te importan los valores de los parámetros de String, y quieres tratar a B y C de la misma manera, así que:
def matcher(l: Foo): String = {
l match {
case A() => "A"
case B(_) | C(_) => "B"
case _ => "default"
}
}
Si debe, debe, debe extraer el parámetro y tratarlos en el mismo bloque de código, podría:
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"
}
}
Aunque creo que sería mucho más limpio descomponerlo en un método:
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"
}
}