CodeGym /Kurse /JAVA 25 SELF /Das Konzept der Polymorphie – wozu sie dient

Das Konzept der Polymorphie – wozu sie dient

JAVA 25 SELF
Level 18, Lektion 0
Verfügbar

1. Einführung

Polymorphie ist eines der drei Grundkonzepte der objektorientierten Programmierung (neben Vererbung und Kapselung). Wörtlich stammt das Wort aus dem Griechischen: „poly“ (viel) und „morph“ (Form). In der Programmierung bedeutet das: ein Interface – viele Implementierungen.

Definition

Polymorphie ist die Fähigkeit von Objekten verschiedener Klassen, auf dieselben Nachrichten (Methodenaufrufe) unterschiedlich zu reagieren.

Das heißt: Wenn Sie eine Methode makeSound() haben, können Sie sie bei jedem Tier aufrufen, aber die Katze miaut, der Hund bellt und die Kuh muht. Für die Programmiererin/den Programmierer ist es einfach der Aufruf animal.makeSound(), aber was tatsächlich passiert, hängt davon ab, welches konkrete Objekt hinter dieser Variablen steht.

Analogie aus dem Alltag

Stellen Sie sich vor, Sie haben zu Hause eine Fernbedienung für den Fernseher, und mit derselben Fernbedienung können Sie auch Lautsprecher, den Projektor und sogar die Kaffeemaschine steuern. Sie drücken die Taste „Einschalten“ – turnOn() – und jedes Gerät reagiert auf seine Weise. Wichtig ist: Alle haben eine „Einschalt‑Taste“, aber die Implementierung ist verschieden.

Beispiel in Java

class Animal {
    void makeSound() {
        System.out.println("Irgendein Geräusch...");
    }
}

class Dog extends Animal {
    @Override
    void makeSound() {
        System.out.println("Wuff!");
    }
}

class Cat extends Animal {
    @Override
    void makeSound() {
        System.out.println("Miau!");
    }
}

class Cow extends Animal {
    @Override
    void makeSound() {
        System.out.println("Muh!");
    }
}

Jetzt können wir Folgendes tun:

Animal animal1 = new Dog();
Animal animal2 = new Cat();
Animal animal3 = new Cow();

animal1.makeSound(); // Wuff!
animal2.makeSound(); // Miau!
animal3.makeSound(); // Muh!

Beachten Sie: Alle Variablen haben den Typ Animal, aber das Ergebnis des Aufrufs hängt vom tatsächlichen Typ des Objekts ab.

2. Arten von Polymorphie

In Java (und in den meisten OOP‑Sprachen) unterscheidet man zwei Hauptarten von Polymorphie:

Kompilierzeitlicher (statischer) Polymorphismus – Methodenüberladung (overloading)

Das ist der Fall, wenn es in einer Klasse mehrere Methoden mit demselben Namen, aber unterschiedlichen Parametern gibt. Der Compiler entscheidet anhand der übergebenen Argumente, welche Methode aufgerufen wird.

Beispiel (ein kleiner Vorausgriff – Details in der nächsten Vorlesung):

class Printer {
    void print(int x) {
        System.out.println("Zahl: " + x);
    }

    void print(String s) {
        System.out.println("Zeichenkette: " + s);
    }
}

Laufzeitlicher (dynamischer) Polymorphismus – Methodenüberschreibung (overriding)

Hier wird eine Methode in der Basisklasse definiert und anschließend in Unterklassen überschrieben. Welche Methode aufgerufen wird, entscheidet sich zur Laufzeit (runtime) abhängig vom tatsächlichen Objekttyp.

Beispiel – siehe oben mit den Tieren.

3. Wozu braucht man Polymorphie?

Polymorphie ist nicht nur ein schönes Buzzword fürs Vorstellungsgespräch. Sie ist ein Werkzeug, das Ihren Code flexibel, erweiterbar und wartungsfreundlich macht.

Allgemeingültiger Code

Sie können Code schreiben, der mit Objekten des Basistyps arbeitet, ohne sich um deren Implementierungsdetails zu kümmern. Wenn Sie etwa eine Liste von Tieren haben, können Sie darüber iterieren und bei jedem makeSound() aufrufen, ohne darüber nachzudenken, ob es eine Katze oder ein Hund ist.

Animal[] animals = { new Dog(), new Cat(), new Cow() };

for (Animal animal : animals) {
    animal.makeSound(); // Jedes Mal wird die "richtige" Methode aufgerufen
}

Einfache Erweiterbarkeit

Wenn morgen Ihr Chef kommt und sagt: „Lass uns einen Papagei hinzufügen!“, schreiben Sie einfach eine neue Klasse Parrot extends Animal und fügen sie dem Array hinzu. Der ganze restliche Code bleibt unverändert. Das ist die Offenheit für Erweiterungen bei Geschlossenheit gegenüber Änderungen (das OCP‑Prinzip aus SOLID).

Vereinfachung der Architektur

Sie können komplexe Systeme bauen, in denen einzelne Teile über Abstraktionen (Basisklassen oder Interfaces) miteinander interagieren, ohne die konkreten Implementierungen zu kennen. Das spart Zeit, Nerven und Kaffee.

4. Schlüsselbegriffe: Referenztyp und tatsächlicher Typ

Referenztyp der Variablen
Wenn Sie Animal animal = new Dog(); schreiben, hat die Variable animal den Referenztyp Animal, d. h. der Compiler „denkt“, dass es sich um ein Tier handelt, und erlaubt nur die Methoden, die in der Klasse Animal deklariert sind.

Tatsächlicher (realer) Objekttyp
Im Speicher liegt jedoch tatsächlich ein Objekt vom Typ Dog. Genau dieser Typ bestimmt, welche Methode beim Aufruf von makeSound() ausgeführt wird.

Veranschaulichung

Animal animal = new Dog();
animal.makeSound(); // Ruft Dog.makeSound() auf, nicht Animal.makeSound()

Wichtig! Über eine Referenz des Basistyps (Animal) können Sie keine Methoden aufrufen, die nur in Dog existieren, sofern sie nicht in der Basisklasse deklariert sind.

Späte (dynamische) Bindung
Das ist die Magie, die zur Laufzeit passiert: Wenn Sie eine Methode über eine Referenz des Basistyps aufrufen, schaut die JVM auf den tatsächlichen Objekttyp und ruft die „richtige“ Implementierung auf. Das ist Polymorphie in Aktion.

5. Praxisbeispiel: Polymorphie in einer Anwendung

Machen wir mit unserer Lernanwendung weiter. Angenommen, wir schreiben eine einfache Zoosimulation. Es gibt eine Basisklasse Animal und mehrere Ableitungen davon. Wir möchten, dass alle Tiere „einen Laut von sich geben“, aber nicht für jede Tierart separaten Code schreiben.

Schritt 1: Basisklasse und Ableitungen

class Animal {
    void makeSound() {
        System.out.println("Irgendein Geräusch...");
    }
}

class Dog extends Animal {
    @Override
    void makeSound() {
        System.out.println("Wuff!");
    }
}

class Cat extends Animal {
    @Override
    void makeSound() {
        System.out.println("Miau!");
    }
}

Schritt 2: Array von Tieren

Animal[] zoo = { new Dog(), new Cat(), new Animal() };

Schritt 3: Iteration und Methodenaufruf

for (Animal animal : zoo) {
    animal.makeSound();
}

Ausgabe:

Wuff!
Miau!
Irgendein Geräusch...

Beachten Sie: Wir wissen nicht im Voraus, wer genau im Array steckt – aber das Programm findet es selbst heraus und ruft die passende Methode auf.

6. Schematische Darstellung der Polymorphie


.        Animal (makeSound)
           /        \
        Dog        Cat
     (makeSound) (makeSound)

Animal animal = new Dog();
animal.makeSound(); // --> Dog.makeSound()

Animal animal = new Cat();
animal.makeSound(); // --> Cat.makeSound()

7. Noch ein Beispiel: Polymorphie in einer realen Aufgabe

Angenommen, Sie schreiben ein Programm zur Verwaltung von Mitarbeitenden in einem Unternehmen. Es gibt eine Basisklasse Employee und zwei Ableitungen: Manager und Developer. Alle Mitarbeitenden können arbeiten – work() –, tun das aber unterschiedlich.

class Employee {
    void work() {
        System.out.println("Der Mitarbeiter arbeitet.");
    }
}

class Manager extends Employee {
    @Override
    void work() {
        System.out.println("Der Manager hält eine Besprechung ab.");
    }
}

class Developer extends Employee {
    @Override
    void work() {
        System.out.println("Der Entwickler schreibt Code.");
    }
}

Jetzt können Sie Folgendes tun:

Employee[] staff = { new Manager(), new Developer(), new Employee() };

for (Employee emp : staff) {
    emp.work();
}

Ergebnis:

Der Manager hält eine Besprechung ab.
Der Entwickler schreibt Code.
Der Mitarbeiter arbeitet.

8. Wann Polymorphie NICHT funktioniert

Polymorphie funktioniert nur für Methoden, die in der Basisklasse deklariert sind. Wenn es in der Unterklasse eine eigene, einzigartige Methode gibt, sehen Sie sie über eine Referenz des Basistyps nicht.

class Dog extends Animal {
    void fetchStick() {
        System.out.println("Der Hund bringt den Stock!");
    }
}

Animal animal = new Dog();
// animal.fetchStick(); // Kompilierfehler! Eine solche Methode ist über Animal nicht sichtbar

Um eine spezifische Methode aufzurufen, müssen Sie die Variable auf den benötigten Typ casten:

if (animal instanceof Dog) {
    ((Dog) animal).fetchStick();
}

Aber das ist eine andere Geschichte – das Wichtigste: Über Polymorphie sind nur die Methoden verfügbar, die in der Basisklasse deklariert sind.

9. Typische Fehler beim Umgang mit Polymorphie

Fehler Nr. 1: Die Erwartung, dass über eine Referenz des Basistyps alle Methoden der Unterklasse verfügbar sind. Tatsächlich sind nur die Methoden verfügbar, die in der Basisklasse deklariert sind.

Fehler Nr. 2: Das Weglassen der Annotation @Override beim Überschreiben einer Methode. Ohne sie kann man versehentlich eine Methode mit falscher Signatur schreiben, und die Polymorphie greift nicht (die Methode der Basisklasse wird nicht überschrieben).

Fehler Nr. 3: Der Versuch, eine spezifische Methode der Unterklasse ohne Type‑Cast aufzurufen. Der Compiler lässt das nicht zu, weil er nicht weiß, welches Objekt sich tatsächlich hinter der Referenz des Basistyps verbirgt.

Fehler Nr. 4: Verwechslung von Überladung (overloading) und Überschreibung (overriding). Überladung bedeutet mehrere Methoden mit demselben Namen, aber unterschiedlichen Parametern in einer Klasse. Überschreibung bedeutet, das Verhalten einer Methode in einer Unterklasse zu ändern.

1
Aufgabe
JAVA 25 SELF, Level 18, Lektion 0
Gesperrt
Abenteuer in der Tierwelt: Lektion über Polymorphie!
Abenteuer in der Tierwelt: Lektion über Polymorphie!
1
Aufgabe
JAVA 25 SELF, Level 18, Lektion 0
Gesperrt
Farmchor: Polymorphismus mit mehreren Stimmen
Farmchor: Polymorphismus mit mehreren Stimmen
1
Aufgabe
JAVA 25 SELF, Level 18, Lektion 0
Gesperrt
Unternehmenslabyrinth: Polymorphismus und Mitarbeiterrolle
Unternehmenslabyrinth: Polymorphismus und Mitarbeiterrolle
1
Aufgabe
JAVA 25 SELF, Level 18, Lektion 0
Gesperrt
Erweiterung des Fuhrparks: Polymorphismus und neue Fahrzeugtypen
Erweiterung des Fuhrparks: Polymorphismus und neue Fahrzeugtypen
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION