Scala Pattern Matching

Scala bietet einen leistungsstarken Pattern-Matching-Mechanismus, der auch weit verbreitet ist.

Ein Pattern Match enthält eine Reihe von Alternativen, die jeweils mit dem Schlüsselwortcasebeginnen. Jede Alternative enthält ein Muster und einen oder mehrere Ausdrücke. Das Pfeilsymbol=>trennt das Muster und die Ausdrücke.

Nachfolgend ein einfaches Beispiel für Pattern Matching mit Ganzzahlwerten:

Beispiel

object Test {
   def main(args: Array[String]) {
      println(matchTest(3))

   }
   def matchTest(x: Int): String = x match {
      case 1 => "one"
      case 2 => "two"
      case _ => "many"
   }
}

Das Ausführen des obigen Codes erzeugt die folgende Ausgabe:

$ scalac Test.scala 
$ scala Test
many

match entspricht switch in Java, wird aber nach dem Selektorausdruck geschrieben. Das heißt:selector match { alternatives }.

Der match-Ausdruck wird ausgewertet, indem jedes Muster in der Reihenfolge geprüft wird, in der es im Code geschrieben steht. Sobald ein passender case gefunden wird, werden die restlichen cases nicht weiter abgeglichen.

Als Nächstes sehen wir uns ein Beispiel für Pattern Matching für verschiedene Datentypen an:

Beispiel

object Test {
   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"
   }
}

Das Ausführen des obigen Codes erzeugt die folgende Ausgabe:

$ scalac Test.scala 
$ scala Test
2
many
one
scala.Int

Im Beispiel entspricht der erste case dem ganzzahligen Wert 1, der zweite case dem Zeichenkettenwert two, und der dritte case einem Typmuster, mit dem festgestellt wird, ob der übergebene Wert eine Ganzzahl ist. Verglichen mit der Verwendung von isInstanceOf zur Typbestimmung ist die Verwendung von Pattern Matching besser. Der vierte case stellt die standardmäßige Volltreffer-Alternative dar, also das Match-Element, wenn keine andere Übereinstimmung gefunden wird, ähnlich wie default in switch.


Verwendung von Case-Klassen

Eine Klassendefinition, die das case-Schlüsselwort verwendet, ist eine Case-Klasse. Case-Klassen sind eine spezielle Art von Klasse, die für Pattern Matching optimiert ist.

Das Folgende ist ein einfaches Beispiel für eine Case Class:

Beispiel

object Test {
   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("Hallo Alice!")
            case Person("Bob", 32) => println("Hallo Bob!")
            case Person(name, age) =>
               println("Alter: " + age + " Jahre, Name: " + name + "?")
         }
      }
   }
   // Case Class
   case class Person(name: String, age: Int)
}

Das Ausführen des obigen Codes erzeugt die folgende Ausgabe:

$ scalac Test.scala 
$ scala Test
Hi Alice!
Hi Bob!
Age: 32 year, name: Charlie?

Wenn eine case class deklariert wird, geschieht automatisch Folgendes:

  • Jeder Parameter des Konstruktors wird zu einem val, es sei denn, er wird explizit als var deklariert, aber dies wird nicht empfohlen;
  • Eine apply-Methode wird im Companion-Objekt bereitgestellt, sodass Objekte ohne Verwendung des new-Schlüsselworts konstruiert werden können;
  • Eine unapply-Methode wird bereitgestellt, damit Pattern Matching funktioniert;
  • toString-, equals-, hashCode- und copy-Methoden werden generiert, es sei denn, diese Methoden sind explizit definiert.
Andere Erweiterungen