EMZETT.
Login

Polymorphism (Polymorphie)

Kurz: Die Fähigkeit, denselben Methodenaufruf auf unterschiedlichen Objekttypen aufzurufen und dabei je nach tatsächlichem Objekt ein anderes Verhalten zu bekommen — “eine Schnittstelle, viele Formen”.

Genauer: Klassisches Beispiel: Eine Liste unterschiedlicher Tier-Unterklassen (Hund, Katze) wird einheitlich als “Tier” behandelt, aber ein Aufruf von machGeraeusch() führt bei jedem Objekt die jeweils eigene, überschriebene Version aus. Möglich wird das durch Vererbung oder durch ein gemeinsames Interface, das mehrere Klassen implementieren, ohne miteinander verwandt zu sein.

Im Detail

class Tier {
    void machGeraeusch() { System.out.println("..."); }
}
class Hund extends Tier {
    void machGeraeusch() { System.out.println("Wuff!"); }
}
class Katze extends Tier {
    void machGeraeusch() { System.out.println("Miau!"); }
}
 
List<Tier> tiere = List.of(new Hund(), new Katze());
for (Tier t : tiere) {
    t.machGeraeusch();   // gibt "Wuff!" bzw. "Miau!" aus - obwohl derselbe Aufruf!
}

Der entscheidende Punkt: Die aufrufende Codestelle (t.machGeraeusch()) weiß zur Kompilierzeit nur, dass t irgendein Tier ist — WELCHE konkrete Version von machGeraeusch() tatsächlich ausgeführt wird, entscheidet sich erst zur LAUFZEIT anhand des tatsächlichen Objekttyps (dynamische Methodenbindung). Das erlaubt es, neue Tier-Unterklassen (z. B. Vogel) hinzuzufügen, ohne den Schleifen-Code überhaupt anzufassen — er funktioniert automatisch mit, solange die neue Klasse dieselbe Methode überschreibt.

Man unterscheidet grob zwei Spielarten von Polymorphie:

  • Vererbungsbasierte Polymorphie: eine Unterklasse überschreibt eine von ihrer Oberklasse geerbte Methode (siehe Beispiel oben).
  • Interface-basierte Polymorphie: völlig unverwandte Klassen implementieren dasselbe Interface und werden darüber einheitlich behandelt — z. B. Auto und Vogel haben nichts gemeinsam außer einem Interface Bewegbar mit einer bewege()-Methode.

Polymorphie ist der zentrale Mechanismus, der es ermöglicht, offenen, erweiterbaren Code zu schreiben (“Open/Closed Principle”: offen für Erweiterung, geschlossen für Änderung) — bestehender Code muss bei neuen Anforderungen (neue Unterklassen) nicht angefasst werden, solange er sich konsequent auf die gemeinsame Ober-/Schnittstellenebene bezieht statt auf konkrete Unterklassen.

Siehe auch: Inheritance, Interface, OOP