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

Scala Grundkurs

Typenparametrisierung

Testen Sie unsere 2016 Kurse

10 Tage kostenlos!

Jetzt testen Alle Abonnements anzeigen
In Scala lassen sich generalisierte Typen auf die Ebene von Funktionen und Klassen abbilden. Die Typenparametrisierung wird beispielsweise verwendet, um eine Liste zu erzeugen, die Elemente eines bestimmten Typs verwaltet.

Transkript

Typenparametrisierung oder auch generalisierte Typen haben einiges an Typenflexiblität bspw. in der Programmiersprache Java geschaffen. Selbstverständlich hat eine Sprache wie Scala, die ein sehr umfangreiches Typensystem hat, genau solche Mechanismen. Man verwendet sie bspw., wenn man eine Liste erzeugen möchte, die Elemente eines bestimmten Types verwaltet. Und selbstverständlich kann man das Ganze auch im Rahmen eigener Klassendefinitionen verwenden, und ich werde Ihnen nun zeigen, wie so eine solche Variable Typenrückgabe für Ihre eigenen Typen definieren können. Ich befinde mich nun in einer Applikation, in der es Kunden gibt, einen Warenkorb, Produkte als auch einen Online-Shop. Die Produkte haben Preise, und aktuell werden diese Preise dadurch dargestellt, dass ein Preis einen Wert hat und eine Währung. Da das sich bei Währungen um eine fixe, definierte Anzahl handelt, wäre das ein Kandidat, das Ganze über das Typensystem zu lösen. Und genau das werde ich nun auf der "case class price" tun. Im Moment gibt es nun also zwei Währungen. Dafür benötige ich also zwei Typen. Diese sind vom Typ "Currency", also Währung. Ich definiere also zunächst einmal eine "trait" für den Typ "Currency". Diese deklariere ich als "sealed", damit sie nur innerhalb dieser Scala-Datei verwendet werden kann. Zumindest in dem Zusammenhang, dass man eine "trait" baut, wie bspw. nun die "trait EUR" , und diese "Currency" erweitern kann. Das Gleiche tue ich nun noch für "USD". Als nächstes muss ich nun einen generalisierten Typen einführen. Dies tue ich mit Hilfe einer Notation mit eckigen Klammern. Hier definiere ich nun bspw. einen Typenparameter "[T]". Als nächstes möchte ich festlegen, ähnlich wie in Java, dass ein Typ "[T]" immer von "Currency" erben muss. Das bedeutet, dass Preise also nur auf Basis der "trait" "Currency" einen Typ bekommen können. Wie bereits zu sehen ist, hat das einige Auswirkungen auf meinen bestehenden Code. Als nächstes möchte ich also, dass Preise nur mit Preisen des gleichen Typs addiert werden können. Aktuell tue ich das durch eine Überprüfung, ob die "Currency" übereinstimmt. Dies kann ich auch dem Typensystem überlassen. Das bedeutet, ein Preis kann nur mit einem anderen Preis vom Typ "[T]" addiert werden. Und das Resultat ist immer ein Preis vom Typ "[T]". Das bedeutet also, wenn mein aktueller Preis bspw. "EUR" ist, kann nur ein anderer Preis in Form von "EUR" mit diesem Preis addiert werden. Aufgrund desssen kann ich mir also alle Überprüfungen sparen und es dem Compiler überlassen. Aktuell habe ich auch eine Konvertierung von einem "EUR"-Preis bspw. in einen "USD"-Preis. Das tue ich, indem ich hier einen Preis zurückgebe. Ich weiß nun sicher, dass dieser Preis immer vom Typ "USD" sein wird, also definiere ich dies. Des Weiteren kann ich nun auf das Feld "Currency" verzichten, und es auch als Parameter für meine "Price"-Klasse entfernen. Außerdem habe ich hier noch eine Hilfesmethode zur Konvertierung, diese basiert aktuell darauf, dass man hier eine "Currency" in Form eines "Strings" angibt. Auch diese Methode muss ich nun neu implementieren. Ich definiere also eine Funktion "convert", die einen Typenparameter entgegennimmt, hier verwende ich nun einen anderen Typ, da ich ja hier in eine andere Währung konvertieren möchte. Dieser Typ muss ähnlich wie bei "[T]" definiert von "Currency" erben. So kann ich also ähnlich wie in Java auch in Scala für bestimmte Methoden und Funktionen Typen entgegennehmen. Das Resultat dieser Funktion ist dann also ein solcher Preis vom Typ "[K]". Nun habe ich die Problemstellung, dass ich wissen muss, was "[K]" für ein Typ ist, um entsprechend in diesem Typ konvertieren zu können. In Java würde ich dies tun, indem ich einen Parameter in Form einer Klasse entgegennehme. In Scala können das die Mechanismen von Reflection für mich automatisch lösen. Dafür nehme ich nun einen impliziten Parameter entgegen und nenne diesen "clazz". In dem Fall mit doppelten Z, da das Wort "class" natürlich reserviert ist für die Sprache. Als nächstes nehme ich nun einen Typ "ClassTag" entgegen, der also hier vom Typ "[K]" ist. Das ist in Scala meine Art und Weise zu sagen, ich würde gerne wissen, um welchen Typ es sich handelt. Nun kann ich innerhalb meiner Implementierung überprüfen, ob diese Klasse mit ihrer Laufzeitklasse der Klasse "USD" übereinstimmt. Wenn das der Fall ist, kann ich nun die Rückgabe "toUSD" aus dieser Funktion geben. Allerdings sollte ich nun noch sicherstellen, dass das Ganze auch vom Typen "[Price[K]]" ist. Ich kann mir in dem Fall zwar sicher sein, dass ein "USD" angefordert wurde, muss aber auch dem Compiler an der Stelle klar machen, dass es sich um den korrekten Typ handelt. In allen anderen Fällen möchte ich eine "Exception" erzeugen, innerhalb derer ich bspw. die Meldung "Invalid currency" zurückgebe. Nun benötige ich nicht mehr die ursprüngliche Implementierung und kann diese entfernen. Als nächstes muss ich noch an anderen Stellen in meinem Code sicherstellen, dass der Typ "Price" entsprechend parametrisiert wird. Aktuell habe ich hier also die "Product"-Klasse, die einen Preis definiert. Dieser ist nun noch untypisiert. Aufgrund dessen möchte ich auch hier definieren, dass hier nur ein "Price" angegeben werden kann, der von "Currency" erbt. Ich definiere also die Vererbung von "Currency", und hier muss ich nun einen Patzhalter hinzufügen. In Java würde ich dies mit Fragezeichen tun, in Scala tu ich dies mit einem "_". Das bedeutet, ein "Product" kann also nur einen Preis entgegen nehmen, dessen Typ so definiert ist, dass er von "Currency" erbt. Diese Änderung muss ich selbstverständlich auch auf erbenden Klassen, die diesen Parameter weiterreichen, tätigen. In dem Fall also hierfür. Zu guter Letzt muss ich noch meine Applikationslogik anpassen. Aktuell nutze ich hier noch die Information über einen "String". Ich entferne also hier die Währung "EUR" und gebe diese als Typenparameter an. Das Gleiche tue ich hier unten. Im dritten Fall für "USD". Und außerdem habe ich keine Funktion mehr mit der Bezeichnung "exchange". Deshalb nutze ich nun stattdessen "convert", und übergebe hier einen Parameter für die Funktion "convert", in dem Fall also zu "USD". Wenn ich meine Applikation nun starte, so erhalte ich wieder mein ursprüngliches Ergebnis, nur habe ich in diesem Fall nun also die Implementierung in ein Typensystem umgewandelt. Mit Hilfe von Typenparametrisierung ist es mir also möglich, variable Typen für Klassen und Methoden festzulegen. Dafür verwende ich die Notation mit eckigen Klammern. Anders als bspw. in Java muss ich keine Klasse in diesem Moment als Parameter übergeben. Ich kann dies bspw. mit Hilfe von Reflection innerhalb eines impliziten Parameters mit dem "ClassTag" lösen. Für meinen Preis habe ich eine Typeneinschränkung definiert. Das bedeutet, dass alle Typen, die für einen Preis verwendet werden durften, immer von "Currency" erben mussten, und letztendlich war es möglich dank der Reflection, die ich beispielsweise innerhalb der Funktion "convert" angewendet habe, dem Nutzer meiner Funktion die Implementierung, beispielsweise eine Übergabe eines Klassenparameters zu ersparen.

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!