Objektorientierung - das Konzept Polymorphie

hhttps://bildung.social/@oerinformatik/113407704530797657

https://oer-informatik.de/uml-klassendiagramm-polymorphie

tl/dr; (ca. 6 min Lesezeit): Ein zentrales Konzept der objektorientierten Programmierung (OOP) ist die Polymorphie: die Vielgestalt von Objekten. Es ermöglicht über Instanztypen das Verhalten eines Objekts festzulegen, während der Typ der Referenz festlegt, welche Member erreichbar sind. Objekte sind so flexibel über unterschiedliche Referenzen wiederverwertbar, ohne gecastet werden zu müssen. (Zuletzt geändert am 09.11.2024)

Dieser Text ist ein Teil der Infotext-Serie zu UML-Klassendiagrammen:

Das Konzept der Polymorphie (Vielgestalt) in der OOP

Bei der Vererbung handelt es sich um eine “ist-ein”-Beziehung zwischen erbenden Klassen. Ein GeschaeftsKonto ist in folgendem Beispiel ein Konto. Ein SparKonto ist ein Konto.

In der Liste kontenListe werden alle Instanzen von Konto + Subklassen verwaltet
In der Liste kontenListe werden alle Instanzen von Konto + Subklassen verwaltet

Die Vielgestalt (Polymorphie) der OOP greift diese Eigenschaft auf: Wenn ein Geschäftskonto ein Konto ist, dann kann ich es auch immer dann verwenden, wenn ich ein Konto verwenden kann. Ein Geschäftskonto kann also in unterschiedlicher Gestalt auftreten und genutzt werden: als Konto oder als Geschäftskonto.

Wir können also Objekte verwenden, ohne genau die Klasse zu kennen, aus der sie instanziiert wurden, solange wir eine ihrer Superklassen (oder Interfaces) kennen und nur deren Methoden verwenden.

Das Konzept lässt sich besser verstehen, wenn wir stark typisierte OOP-Sprachen (wie z.B. Java) betrachten, da hier zwischen dem deklarierten Referenztyp der Variablen und der Klasse der zugrundeliegenden Instanz unterschieden wird. Dynamisch typisierte Sprachen (wie z.B. Python) kennen das Konzept eines Referenztyps nicht.

In stark typisierten Sprachen können wir Instanzen einer Subklasse mit Referenzen einer Superklasse ansprechen. Am Beispiel von Java sieht für unser obiges Beispiel etwa so aus:

Auch wenn die Referenz vom Typ der Superklasse ist: die aufgerufene Implementierung ist die der jeweiligen Unterklasse. Ein SparKonto kann nach außen auch die Gestalt eines Konto oder eines PrivatKonto annehmen - das ist die Vielgestalt, die Polymorphie.

In stark typisierten OOP-Sprachen wie Java hat das zur Folge, dass wir unterscheiden müssen, wessen Instanz ein Objekt ist und über welche Referenz es angesprochen wird. Wir erweitern unser Ausgangsbeispiel um ein Interface und fügen ein paar Details der Klassen an, um es plastischer zu machen:

In der Liste kontenListe werden alle Instanzen von Konto + Subklassen verwaltet
In der Liste kontenListe werden alle Instanzen von Konto + Subklassen verwaltet

Mit diesem Wissen betrachten wir die folgenden Zeile genauer:

Der Referenztyp von konto3 ist Konto, es ist aber eine Instanz der Klasse GeschaeftsKonto. Wir glauben also, es mit einem Konto zu tun zu haben und können nur Konto-Methoden aufrufen. Der Aufruf konto3.setVerfuegungsrahmen() spricht keine Methode von Konto an und ist daher für konto3 nicht verfügbar.

Mit dem Namen konto5 haben wir ein weiteres Geschäftskonto erzeugt, das wir diesmal über eine Geschäftskonto-Referenz ansprechen. konto5.setVerfuegungsrahmen() ist also aufrufbar.

Der Referenztyp legt fest, welche Member der Klasse erreichbar sind.

Der Instanztyp von konto3 ist GeschaeftsKonto. Wenn wir konto3.auszahlen() aufrufen reagiert die Implementierung auszahlen(), die in GeschaeftsKonto festgelegt wurde. Dass konto3 eine Konto-Referenz ist, spielt hier keine Rolle:

Der Instanztyp legt fest, welche Implementierung bei Aufruf ausgeführt wird.

Die gleichen Überlegungen können wir für Interfaces treffen:

Der Referenztyp Zahlbar legt fest, dass wir nur die Methoden des Interfaces Zahlbar direkt aufrufen können (einzahlen(), auszahlen()). Der Instanztyp ist ein Privatkonto, es wird also die Implementierung genutzt, die in Privatkonto gilt. In diesem Fall wäre das die von Konto geerbte Implementierung, da sie nicht überschrieben wurden.

Das ermöglicht uns beispielsweise, alle Instanzen von Konto und deren Subklassen zentral zu verwalten, in dem die Superklasse eine Liste aller Konten als Klassenvariable (statisch) hält und verwaltet.

Im Quelltext muss das neue Klassenattribut und die Klassenvariable in Konto eingefügt werden (sowie der Import für java.util.ArrayList):

Bereits so würde die polymorphe Struktur sichtbar, da die aufgerufene toString()-Methode (diese erben alle Java-Objekte von der Klasse Object) den Instanztyp ausgibt:

Alle Konten:
 - de.csbme.kontoverwaltung.Konto@5c8da962
 - de.csbme.kontoverwaltung.PrivatKonto@33e5ccce
 - de.csbme.kontoverwaltung.GeschaeftsKonto@5a42bbf4
 - de.csbme.kontoverwaltung.SparKonto@270421f5

Deutlich komfortabler wird die Ausgabe, wenn jede Klasse eine eigene Implementierung von toString() enthält, in der alle spezifischen Attributwerte ausgegeben werden (getIban() muss noch in Konto implementiert werden):

Für Konto:

Für PrivatKonto:

Für GeschäftsKonto:

Für SparKonto:

Nach den Anpassungen ist der polymorphe Aufruf unterschiedlicher Instanztypen über eine Konto-Referenz in der Liste ebenso gut sichtbar, wie die Tatsache, dass jede Instanz die eigene Implementierung nutzt. Zudem sind die bei Aufruf über die Konto-Referenz zunächst unsichtbaren Methoden und Attribute für die jeweilige (interne) toString()-Methode weiterhin aufrufbar und Detailinformationen verfügbar:

Alle Konten:
 - Konto DE123 / Kontostand 500.0
 - Privatkonto DE456 von Max Mustermann/ Kontostand: 1000.0
 - Geschäftskonto DE789 von Muster GmbH/ Kontostand: 1601.0 / Verfügungsrahmen: 400.0
 - Sparkonto DE987 von Max Mustermann/ Kontostand: 102.0 / Zins: 2,00%

Hinweis zur Nachnutzung als Open Educational Resource (OER)

Dieser Artikel und seine Texte, Bilder, Grafiken, Code und sonstiger Inhalt sind - sofern nicht anders angegeben - lizenziert unter CC BY 4.0. Nennung gemäß TULLU-Regel bitte wie folgt: Objektorientierung - das Konzept Polymorphie” von oer-informatik.de (H. Stein), Lizenz: CC BY 4.0. Der Artikel wurde unter https://oer-informatik.de/uml-klassendiagramm-polymorphie veröffentlicht, die Quelltexte sind in weiterverarbeitbarer Form verfügbar im Repository unter https://gitlab.com/oer-informatik/uml/umlklasse. Stand: 09.11.2024.

[Kommentare zum Artikel lesen, schreiben] / [Artikel teilen] / [gitlab-Issue zum Artikel schreiben]

Kommentare gerne per Mastodon, Verbesserungsvorschläge per gitlab issue (siehe oben). Beitrag teilen: