Unsere Datenschutzrichtlinie wird in Kürze aktualisiert. Bitte sehen Sie sich die Vorschau an.

Scala Grundkurs

Implizite Parametrisierung

Testen Sie unsere 2019 Kurse

10 Tage kostenlos!

Jetzt testen Alle Abonnements anzeigen
Durch implizite Parametrisierung ist es möglich, die Übergabe technischer Parameter innerhalb von Kontexten zu automatisieren.

Transkript

Implizite Parametrisierung ist eine der Mechanismen von Scala, der oft den Eindruck vermittelt, dass Scala sehr komplex ist. Wenn man allerdings die Hintergründe von impliziter Parametrisierung versteht, versteht man relativ schnell, dass dieser Mechanismus in der Praxis sehr nützlich ist. Schließich erwischt man sich selbst oft dabei, dass man innerhalb bspw. von Businesslogik formale oder technische Parameter übergeben muss, nur weil der Programmcode es erfordert. Genau das kann man mit Hilfe von impliziter Parametrisierung vermeiden Und ich zeige Ihnen nun, wie genau. Ich befinde mich nun in meinem Programmcode. Hier gibt es also einen Kunden und einen Warenkorb als auch Produkte, die der Kunden in den Warenkorb packt, letztendlich mit seinem Bank-Konto bezahlt und über den Online-Shop bestellt. Nach der bezahlung bekommt der Kunde allerdings in diesem Programm aktuell noch keine Rechnung, und genau das möchte ich nun ermöglichen. Dafür erzeuge ich zunächst einmal eine "case class" mit der Bezeichnung "Bill". Um die Implementierung möglichst einfach zu halten, enthält eine solche Rechnung also zunächst einmal die Liste der gekauften Produkte als auch den Gesamtpreis. Genau ein solches Rechnungsobjekt muss ich nun also erzeugen im Rahmen des "checkout"-Prozesses. Dafür verwende ich also meinen "CheckoutHandler" und dort den Aufruf "checkout". Hier füge ich nun zusätzlich ein Feld hinzu, das die Rechnung nach Wunsch erzeugt. Die Produkte bekomme ich also aus dem Warenkorb, und den Gesamtpreis habe ich bereits berechnet. An und für sich ist das Ganze schon sinnvoll, allerdings kann ich die Rechnung z. B. jetzt nicht drucken, dafür wäre es also praktisch, einen Drucker zu haben. Ich erstelle mir nun einen solchen Drucker in Form einer Klasse. Dieser soll also nur einen Drucker simulieren. Mein Drucker trägt nun einen Namen, und er kann ein Dokument drucken. Beispielsweise also eine Rechnung. Es gibt hier keine Ausgabe, und alles, was passiert, ist letztendlich ein "println" genau dieser Rechnung. Als nächstes definiere ich innerhalb meines Codes also zwei solche Drucker. Zum Beispiel gibt es den USB-Drucker, der auch "USB Printer" heißt als auch einen "Network Printer". Wenn ich nun also bspw. nach erfolgtem Kauf die Rechnung drucken möchte, könnte ich dies tun, indem ich bspw. einen dieser Printer verwende, dann "printDocument" aufrufe, und mir aus dem "checkout"-Objekt die Rechnung geben lasse. Doch vom Programmcode her gesehen sage ich nun also einem Drucker, dass er ein Dokument drucken soll. Doch eigentlich möchte ich nur, dass einfach das Dokument gedruckt wird. Das heißt, ich möchte das ganz aus Sicht des Dokuments abbilden. Dafür begebe ich mich nochmal in die "case class" "Bill". Als nächstes definiere ich hier also nun eine Methode "print", diese nimmt zunächst einmal keinen Parameter entgegen, und gibt auch keinen Rückgabewert aus. Theoretisch bräuchte ich jetzt nun also einen Drucker, um konkret drucken zu können. Den Drucker möchte ich nun aber als impliziten Parameter erhalten, das heißt, ich definiere ihn nun als zusätzliches Argument für meine Printmethode. Ich sage also "implicit", als Keyword "printer", und ein solcher Printer muss eben vom Typ "Printer" sein. Mit einem solchen Printer kann ich dann "printDocument" als Methode aufrufen, und ihm die aktuelle Instanz übergeben. Das bedeutet, dass ich jetzt anders herum vom Rechnungsdokument kommen kann, und hier "Print" aufrufe, allerdings wird das Ganze so nicht ohne weiteres funktionieren. Ich starte hier kurz ein "Rebuild" und erhalte nun die Fehlermeldung, dass der implizite Parameter nicht gefunden werden konnte. In dem Moment, wo eine Methode einen solchen impliziten Parameter anfordert, habe ich mehrere Möglichkeiten, diesen anzugeben. Ich könnte das nun bspw. ganz konkret tun, indem ich eine weitere Klammer öffne und nun einem Drucker übergebe. Beispielsweise dem USB-Drucker. Damit wird also nun meine Rechnung auf die Konsole gedruckt. Allerdings ist genau das nicht Sinn und Zweck eines impliziten Parameters. Schließlich soll dieser sich aus dem Kontext erschließen lassen. Das heißt, ich entferne nun diesen "usbPrinter" und definiere nun hier zusätzlich das Keyword "implicit" vor dem "usbPrinter". Das heißt, nun wurde der "USB Printer" genutzt, weil er innerhalb dieses Kontextes zur Verfügung steht. Ich muss ihn also nicht mehr zusätzlich als Argument angeben. Das Ganze basiert darauf, dass es hier in diesem Kontext nur einen "implicit"-Wert gibt, der den Typ "Printer" hat. Wenn ich nun bspw. einen zweiten impliziten Parameter vom Typ "Printer" definiere, so werde ich eine Fehlermeldung erhalten. Denn der Scala-Compiler kann nun nicht unterscheiden, welcher Drucker tatsächlich gemeint ist. Unter Umständen könnte ich mit diesem Mechanismus allerdings nun verschiedene Methoden bauen, die auf Drucker aufbauen, und müsste nicht an dieser Stelle ständig das Argument des Druckers wiederholen. Wichtig ist, der Scope eines solchen "implicit"-Parameter ist immer der "Block Scope", unter dem er erzeugt wird. In dem Fall also der "Block Scope" der Methode "main". Sobald ich also die "main"-Methode verlasse, ist der USB Printer nicht mehr als impliziter Parameter verfügbar, und andere Aufrufe bspw. der Printfunktion würden nicht mehr funktionieren. Denn diese bräuchten wiederum einen neu definierten impliziten Parameter. Die Mechanik des impliziten Parameters findet man innerhalb von Scala vor allem bei dem Arbeiten mit Features und einem sogenannten "Execution Context". Ich habe also nun einen impliziten Parameter auf einer Methode definiert, und einen solchen mithilfe einer "implicit val"-Deklaration innerhalb des Codes definiert. Entscheidend ist hier, dass es sich dabei auch um eine Konstante in Form von "val" handelt. Denn der implizite Parameter ist nicht mehr veränderlich nachdem er erzeugt wurde. Solche implicit-Parameter lassen sich dann auf einer Methode oder Funktion als erweiterte Parameter übergeben. Sollte ich explizit einen Typ übergeben wollen, statt dem implicit-Mechanismus, kann ich dies tun. Das habe ich bspw. zu Anfang getan, als ich den USB-Drucker noch direkt an die Print-Methode übergeben habe. Die automatische Übergabe, die der Scala-Compiler hier einleitet, findet anhand von Typengleichheit statt. Gibt es also bspw. zwei gleiche Typen innerhalb eines solchen Kontextes, so wird das nicht funktionieren.

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!