relaciones paso modelo entre ejemplos diagrama clases clase scala pattern-matching

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" } }