Am 14. September 2017 haben wir eine überarbeitete Fassung unserer Datenschutzrichtlinie veröffentlicht. Wenn Sie video2brain.com weiterhin nutzen, erklären Sie sich mit diesem überarbeiteten Dokument einverstanden. Bitte lesen Sie es deshalb sorgfältig durch.

Scala Grundkurs

Pattern Matching

LinkedIn Learning kostenlos und unverbindlich testen!

Jetzt testen Alle Abonnements anzeigen
Um komplexe Überprüfungen von Zuständen - ähnlich der Semantik eines switch-Statements - durchzuführen, steht Ihnen das sogenannte Pattern Matching zur Verfügung. In diesem Video geht Christopher Janietz ausführlich auf dieses Thema ein und zeigt Ihnen detailliert den Einsatz von Pattern Matching.

Transkript

Pattern-Matching ist ein Mechanismus, den man aus Programmiersprachen wie beispielsweise Haskell kennt. Die Problemstellung, dem sich Pattern-Matching vor allem annimmt, ist, dass man mit regulären Switches nicht viele Komplexitäten abbilden kann. Stattdessen verlässt man sich in Programmiersprachen wie Java vor allem auf If-Blöcke, die mit hoher Komplexität und Schachtelung verbunden sind. Aufgrund des starken Typensystems und dem Pattern-Matching lassen sich solche Komplexitäten in Scala relativ einfach abbilden. Und ich möchte Sie nun nicht weiter auf die Folter spannen, wie das Ganze funktioniert. Befinde mich nun in meiner Anwendung. Hier gibt es eine Case Class mit der Bezeichnung "Price". Aktuell kann diese Case Class also mit anderen Preisen verrechnen, beispielsweise kann ich einen Preis zum anderen Preis addieren. Des Weiteren kann ich einen Preis in US-Dollar umwandeln, insofern er sich aktuell nicht auf US-Dollar befindet, beispielsweise der Währung Euro. Allerdings habe ich hier, mittlerweile bereits ersichtlich, eine Komplexität von verschiedenen If-Blöcken, die sich mitunter auch schwierig lesen lassen und bei denen sich die Fehlerbehandlung auch als schwierig gestaltet. Genau für diesen Zweck möchte ich hier nun Pattern-Matching einsetzen. Den einfachsten Fall, den ich mit Pattern-Matching abbilden kann, ist zum Beispiel, zu überprüfen, ob "newCurrency" den Wert "USD" enthält. Ich entferne also den aktuell bestehenden If-Block und tausche ihn. Ich möchte nun also das Feld "newCurrency" auswerten, also schreibe ich "newCurrency" und dann den Ausdruck "match". Als nächstes öffne ich nun geschweifte Klammern. Ab jetzt beginnt das Pattern-Matching. Das einfachste, was ich nun sagen kann, ist, in dem Moment, wo es sich hierbei um USD handelt, ist der Rückgabewert das, was innerhalb der Funktion "toUSD" generiert wird. Sollte es sich nun um eine andere Währung handeln, kann ich einen Standard-File implementieren, ähnlich wie in einem Switch. In dem Fall kann ich nun dem Wert einen variablen Namen geben, beispielsweise den Namen "otherCurrency". Und darauf basierend kann ich also beispielsweise eine Exception erzeugen mit dem Inhalt "No converter exists for otherCurrency". Damit habe ich also nun schon mein erstes Pattern-Matching geschrieben. Allerdings hätte man auch genau das noch mit einem Switch abbilden können, doch wie wäre es nun mit der Funktion "toUSD"? Hier möchte ich also meinen aktuellen Preis in US-Dollar umwandeln. Aktuell passiert das also mit Hilfe eines Currency Converters. Momentan überprüfe ich hier weder, ob es sich aktuell um Euro oder japanische Yen beispielsweise handelt oder bereits um US-Dollar. Ich entferne also nun diesen gesamten Ausdruck und nutze nun meine aktuelle Instanz, also "this", und matche diese. Als Nächstes kann ich nun eine Besonderheit nutzen. Die Besonderheit äußert sich darin, dass ich hier eine Case Class verwende, das heißt, meine aktuelle Instanz ist also eine Case Class vom Typ "Price". Als solche kann ich hier eine Destrukturierung vornehmen, das heißt, ich gebe hier also nun die Case Class "Price" an und kann nun die Felder, die hier normalerweise beim Erzeugen des Price definiert werden, innerhalb meines Pattern-Matchings nutzen. Zum Beispiel könnte ich nun sagen, mich interessiert der Wert nicht. Stattdessen interessiert mich die Währung Euro. Ist es also der Fall, dass es sich hierbei um Euro handelt? Nutze ich also nun die Möglichkeit, meine aktuelle Instanz zu kopieren, bestimme den Wert dadurch, dass ich den aktuellen Umrechnungsfaktor mit dem aktuellen Wert verrechne und das Ganze auf die Währung US-Dollar umstelle. Die Besonderheit liegt also nun darin, dass ich hier ganz konkret einen Wert angeben kann, nach dem geprüft wird. Ich muss hier nicht explizit einen Stringvergleich starten. Das passiert automatisch. Nun könnte ich aber unter Umständen besondere Anforderungen haben, die sich nicht mit einem solchen Destructuring so einfach abbilden lassen. Dafür definiere ich nun wieder die gleiche Struktur, aber im Gegensatz dazu, hier einen fixen Wert zu hinterlegen, sage ich: Immer dann, wenn das Feld "otherCurrency" vom Typ "String" ist, genau dann möchte ich nun eine Auswertung machen, und zwar mithilfe eines If-Ausdrucks. Das bedeutet, ich kann auch einen If-Ausdruck in beliebiger Komplexität zu meinem Case-Match-Statement hinzufügen. Zum Beispiel könnte ich nun hier manuell prüfen, ob "otherCurrency" den Wert "Japanischer Yen" enthält. Ist das der Fall, gehe ich ähnlich vor, lege also den Wert dadurch fest, dass ich das Ganze mit dem Faktor 0,0087 multipliziere und die Currency in dem Moment auf US-Dollar fixiere. Selbstverständlich sollte ich noch Vorkehrungen dafür treffen, dass beispielsweise nun andere Währungen genutzt werden, für die ich aktuell keinen Fall definiert habe. In dem Fall gebe ich beispielsweise wieder einen Fehler aus in Form einer Exception, beispielsweise mit dem Inhalt "Could not convert from otherCurrency to USD". Egal, was passiert, ich sollte nach Möglichkeiten immer die Möglichkeiten des Pattern-Matching komplett ausnutzen. So kann ich auch einen Case definieren, der immer dann stattfindet, wenn überhaupt nichts zutrifft, hier dadurch signalisiert, dass ich Underscore verwende. Genau dann möchte ich auch eine Runtime Exception generieren, die beispielsweise aussagt: "Could not convert to USD", also sehr generisch. Hiermit bilde also nun gerade eine gesamte Funktion ab. Alternativ kann ich auch Folgendes tun. Definiere nun also eine zweite Funktion "toUSD" und ich nehme nun das gesamte Match-Statement und übergebe nun lediglich aus dem Match-Statement einen Faktor, zum Beispiel hier 1,07 oder hier 0,087. Zu guter Letzt dann also noch der Aufruf von "copy", in dem sich der Wert nun daraus definiert, dass er mit dem Faktor multipliziert wird und die Currency in dem Fall US-Dollar ist. Dadurch habe ich einige Redundanzen vermieden. Und da es sich hierbei um ein Statement handelt, kann ich es auch ähnlich betrachten, da es hier also einen Return-Wert gibt, der aus dieser Auswertung resultiert. Zu guter Letzt habe ich hier noch einen Dorn im Auge. Beim Zusammenrechnen von Preisen überprüfe ich, ob die Währungen der beiden Preise übereinstimmen. Das Ganze kann ich auch mithilfe eines Pattern-Matching abbilden. Dafür nehme ich nun nicht mehr nur noch die aktuelle Instanz, sondern auch den anderen Preis. Diese fasse ich in einem Tupel zusammen und beginne damit mein Case-Matching-Statement. Als Nächstes verwende ich nun diese Klammern und kann hier ein Pattern-Matching vornehmen, dass sich für den einen und den anderen Preis jeweils separat festlegen lässt. Beispielsweise kann ich so also den ersten Wert und den zweiten Wert extrahieren als auch die jeweilige Währung. Falls die beiden Währungen übereinstimmen, also "thisCurrency" gleich "otherCurrency" ist, genau dann ist das Addieren eine Operation, die durch das Addieren der beiden Werte stattfindet. Auch hier sollte ich selbstverständlich für den anderen Fall vorsorgen, dass die beiden Währungen nicht übereinstimmen. Ich kopiere also das Case-Matching-Statement und ändere das Ganze in einen Inequals-Ausdruck. In dem Moment erzeuge ich eine Exception, die aussagt, dass man die beiden Währungen nicht miteinander addieren kann. Als Nächstes gilt es, das Ganze noch zu testen. Die übliche Funktion ist also das Verrechnen von zwei Euro-Preisen. Wenn ich wiederum versuche, einen Euro- und einen US-Dollar-Preis zu berechnen, sollte ich einen Fehler bekommen. Dafür nutze ich nun die Try-Funktion und addiere also einen Euro-Preis und einen US-Dollar-Preis und sowohl Fehlermeldung als auch möglichen Wert übergebe ich an den "println"-Befehl. Was nun auch möglich sein sollte, ist das Konvertieren von einem Euro-Preis in US-Dollar und dann das Verrechnen mit einem US-Dollar-Preis. Ein Preis, der in Hongkong-Dollar angegeben ist, hat aktuell keine Implementierung. Das bedeutet, dass eine Umrechnung in US-Dollar nicht möglich sein sollte. Und zu guter Letzt möchte ich noch einmal den japanischen Yen in US-Dollar konvertieren und mit dem US-Dollar-Preis verrechnen. Wie erwartet, die Euro-Verrechnung ist positiv. Ich erhalte den Wert 40 Euro. Ich kann aktuell keinen Euro mit US-Dollar verrechnen, allerdings kann ich einen Euro in US-Dollar umwandeln und dann mit US-Dollar verrechnen. Hongkong-Dollar können nicht in US-Dollar umgewandelt werden. Und ein japanischer Yen kann in US-Dollar konvertiert werden und dann mit US-Dollarn verrechnet werden. An und für sich ist also ein Pattern-Matching-Mechanismus zunächst einmal ein komplexeres Switch-Statement, da er deutlich mehr Logik abbilden kann, als ein regulärer Switch es kann. Durch die Fall- und Ausnahmefalldefinition kann man also, soweit es geht, alles abdecken, was tatsächlich in der Realität vorkommt. Durch seine flache Struktur ist vor allem das Sehen und Erkennen von Ausnahmefällen deutlich einfacher, als es beispielsweise mit If- und Else-Blöcken möglich ist. Innerhalb solcher Match-Statements können sowohl Wertprüfungen als auch Typprüfungen vorgenommen werden. Sollten mir allerdings diese Möglichkeiten nicht reichen, kann ich das Ganze noch um If-Bedingungen erweitern und damit eigentlich alles abdecken, was tatsächlich auch mit Ifs möglich wäre. Pattern-Matching wird häufig auch im Zusammenhang mit partiellen Funktionen eingesetzt. Dabei ist es möglich, quasi eine Art Chaining vorzunehmen von verschiedenen Pattern-Matching-Statements hintereinander. Und besonders gut geeignet ist das Pattern-Matching für eine Verwendung mit Case-Klassen, Tupeln oder auch anderen Listentypen.

Scala Grundkurs

Entdecken Sie die Möglichkeiten und Eigenschaften der modernen Programmiersprache Scala.

4 Std. 44 min (39 Videos)
Derzeit sind keine Feedbacks vorhanden...
 
Exklusiv für Abo-Kunden
Erscheinungsdatum:12.04.2017

Dieser Online-Kurs ist als Download und als Streaming-Video verfügbar. Die gute Nachricht: Sie müssen sich nicht entscheiden - sobald Sie das Training erwerben, erhalten Sie Zugang zu beiden Optionen!

Der Download ermöglicht Ihnen die Offline-Nutzung des Trainings und bietet die Vorteile einer benutzerfreundlichen Abspielumgebung. Wenn Sie an verschiedenen Computern arbeiten, oder nicht den ganzen Kurs auf einmal herunterladen möchten, loggen Sie sich auf dieser Seite ein, um alle Videos des Trainings als Streaming-Video anzusehen.

Wir hoffen, dass Sie viel Freude und Erfolg mit diesem Video-Training haben werden. Falls Sie irgendwelche Fragen haben, zögern Sie nicht uns zu kontaktieren!