Scala Pattern Matching
Scala proporciona un potente mecanismo de pattern matching, y su aplicación es muy amplia.
Un pattern matching contiene una serie de alternativas, cada una comienza con la palabra clavecase. Cada alternativa contiene un patrón y una o más expresiones. El símbolo de flecha=>separa el patrón y las expresiones.
A continuación se muestra un ejemplo simple de pattern matching con valores enteros:
Ejemplo
def main(args: Array[String]) {
println(matchTest(3))
}
def matchTest(x: Int): String = x match {
case 1 => "one"
case 2 => "two"
case _ => "many"
}
}
Al ejecutar el código anterior, la salida es:
$ scalac Test.scala $ scala Test many
match corresponde a switch en Java, pero se escribe después de la expresión del selector. Es decir:selector match {alternativas}.
La expresión match se evalúa intentando cada patrón en el orden en que está escrito en el código; en cuanto encuentra un case que coincide, los case restantes no se siguen evaluando.
A continuación veamos un pattern matching con diferentes tipos de datos:
Ejemplo
def main(args: Array[String]) {
println(matchTest("two"))
println(matchTest("test"))
println(matchTest(1))
println(matchTest(6))
}
def matchTest(x: Any): Any = x match {
case 1 => "one"
case "two" => 2
case y: Int => "scala.Int"
case _ => "many"
}
}
Al ejecutar el código anterior, la salida es:
$ scalac Test.scala $ scala Test 2 many one scala.Int
En el ejemplo, el primer case corresponde al valor entero 1, el segundo case corresponde al valor de cadena two, el tercer case corresponde al patrón de tipo, que se usa para determinar si el valor pasado es un entero. En comparación con usar isInstanceOf para juzgar el tipo, es mejor usar pattern matching. El cuarto case representa la alternativa predeterminada de coincidencia total, es decir, el caso de coincidencia cuando no se encuentra otra coincidencia, similar a default en switch.
Usar case classes
Una definición de clase que utiliza la palabra clave case es una case class. La case class es un tipo especial de clase, optimizada para usarse en pattern matching.
A continuación se muestra un ejemplo simple de case class:
Ejemplo
def main(args: Array[String]) {
val alice = new Person("Alice", 25)
val bob = new Person("Bob", 32)
val charlie = new Person("Charlie", 32)
for (person <- List(alice, bob, charlie)) {
person match {
case Person("Alice", 25) => println("Hi Alice!")
case Person("Bob", 32) => println("Hi Bob!")
case Person(name, age) =>
println("Age: " + age + " year, name: " + name + "?")
}
}
}
// case class
case class Person(name: String, age: Int)
}
Al ejecutar el código anterior, la salida es:
$ scalac Test.scala $ scala Test Hi Alice! Hi Bob! Age: 32 year, name: Charlie?
Al declarar una case class, ocurre automáticamente lo siguiente:
- Cada parámetro del constructor se convierte en val, a menos que se declare explícitamente como var, pero no se recomienda hacerlo;
- El método apply se proporciona en el objeto acompañante, por lo que se puede construir un objeto sin usar la palabra clave new;
- Se proporciona el método unapply para que funcione el pattern matching;
- Se generan los métodos toString, equals, hashCode y copy, a menos que se proporcionen definiciones explícitas de estos métodos.