Polymorphie

Polymorphie ist ein OOP-Konzept, bei dem Objekte unterschiedlicher Klassen auf denselben Methodenaufruf unterschiedlich reagieren können.

Auf dieser Seite

Polymorphie (griechisch für “Vielgestaltigkeit”) ist eines der fundamentalen Konzepte der objektorientierten Programmierung (OOP). Sie ermöglicht es, dass Objekte unterschiedlicher Klassen auf denselben Methodenaufruf unterschiedlich reagieren können. Zusammen mit Vererbung und Kapselung bildet Polymorphie die drei Säulen der OOP.

Definition und Grundprinzip

Das Wort Polymorphie stammt aus dem Griechischen und setzt sich aus “poly” (viel) und “morph” (Gestalt) zusammen. In der Programmierung bedeutet dies: Eine Methode kann in verschiedenen Klassen unterschiedlich implementiert sein, obwohl sie denselben Namen und dieselbe Signatur trägt.

Der entscheidende Vorteil: Du kannst Objekte verschiedener Klassen einheitlich behandeln, solange sie eine gemeinsame Schnittstelle oder Oberklasse teilen. Der konkrete Code, der ausgeführt wird, hängt vom tatsächlichen Typ des Objekts zur Laufzeit ab.

Arten der Polymorphie

In der objektorientierten Programmierung unterscheidet man zwei Hauptarten von Polymorphie, die zu unterschiedlichen Zeitpunkten aufgelöst werden:

Statische Polymorphie (Compile-Zeit)

Bei der statischen Polymorphie wird bereits zur Compile-Zeit entschieden, welche Methode aufgerufen wird. Das bekannteste Beispiel ist die Methodenüberladung (Method Overloading): Mehrere Methoden tragen denselben Namen, unterscheiden sich aber in ihrer Parameterliste.

public class Rechner {
    // Überladene Methoden mit gleichem Namen
    public int addiere(int a, int b) {
        return a + b;
    }
    
    public double addiere(double a, double b) {
        return a + b;
    }
    
    public int addiere(int a, int b, int c) {
        return a + b + c;
    }
}

Der Compiler wählt anhand der übergebenen Argumente die passende Methode aus. Dies geschieht vor der Programmausführung, daher “statisch”.

Dynamische Polymorphie (Laufzeit)

Die dynamische Polymorphie ist das eigentliche Herzstück der OOP. Hier wird erst zur Laufzeit entschieden, welche Methode ausgeführt wird. Sie basiert auf Methodenüberschreibung (Method Overriding): Eine Unterklasse definiert eine Methode der Oberklasse neu.

// Abstrakte Oberklasse
abstract class Tier {
    public abstract void gibLaut();
}

// Konkrete Unterklassen
class Hund extends Tier {
    @Override
    public void gibLaut() {
        System.out.println("Wuff!");
    }
}

class Katze extends Tier {
    @Override
    public void gibLaut() {
        System.out.println("Miau!");
    }
}

// Polymorphe Verwendung
public class Main {
    public static void main(String[] args) {
        Tier meinTier = new Hund();  // Referenz vom Typ Tier
        meinTier.gibLaut();          // Ausgabe: Wuff!
        
        meinTier = new Katze();      // Gleiche Referenz, anderes Objekt
        meinTier.gibLaut();          // Ausgabe: Miau!
    }
}

Das Schlüsselprinzip: Die Variable meinTier hat den Typ Tier, aber das tatsächliche Verhalten wird durch den konkreten Objekttyp (Hund oder Katze) bestimmt.

Polymorphie mit Interfaces

Neben Vererbung kannst du Polymorphie auch durch Interfaces (Schnittstellen) erreichen. Verschiedene Klassen implementieren dasselbe Interface und können dadurch einheitlich behandelt werden:

// Interface definiert den Vertrag
interface Zeichenbar {
    void zeichne();
}

// Verschiedene Klassen implementieren das Interface
class Kreis implements Zeichenbar {
    @Override
    public void zeichne() {
        System.out.println("Zeichne einen Kreis");
    }
}

class Rechteck implements Zeichenbar {
    @Override
    public void zeichne() {
        System.out.println("Zeichne ein Rechteck");
    }
}

// Polymorphe Verarbeitung
public void alleZeichnen(List<Zeichenbar> formen) {
    for (Zeichenbar form : formen) {
        form.zeichne();  // Jede Form weiß selbst, wie sie sich zeichnet
    }
}

Interfaces sind besonders wertvoll, weil sie Polymorphie ohne Vererbungshierarchie ermöglichen. Eine Klasse kann mehrere Interfaces implementieren und dadurch in verschiedenen polymorphen Kontexten verwendet werden.

Vorteile der Polymorphie

Polymorphie bietet erhebliche Vorteile für die Softwareentwicklung und ist ein Grund, warum objektorientierte Programmierung so verbreitet ist:

  • Erweiterbarkeit: Neue Klassen können hinzugefügt werden, ohne bestehenden Code zu ändern
  • Wartbarkeit: Änderungen an einer Klasse betreffen nicht den Code, der sie polymorph verwendet
  • Wiederverwendbarkeit: Generischer Code funktioniert mit allen kompatiblen Typen
  • Lesbarkeit: Einheitliche Schnittstellen machen den Code verständlicher
  • Testbarkeit: Mock-Objekte können echte Implementierungen ersetzen

Polymorphie in verschiedenen Programmiersprachen

Das Konzept der Polymorphie existiert in allen objektorientierten Sprachen, wird aber unterschiedlich umgesetzt:

Java

Java verwendet das Schlüsselwort extends für Vererbung und implements für Interfaces. Methoden sind standardmäßig überschreibbar, außer sie sind als final markiert. Die Annotation @Override dokumentiert beabsichtigte Überschreibungen.

C#

In C# müssen Methoden explizit als virtual deklariert werden, um überschreibbar zu sein. Die Überschreibung erfolgt mit dem Schlüsselwort override. Dies macht Polymorphie sichtbarer im Code.

class Tier {
    public virtual void GibLaut() {
        Console.WriteLine("Tier macht Geräusch");
    }
}

class Hund : Tier {
    public override void GibLaut() {
        Console.WriteLine("Wuff!");
    }
}

Python

Python nutzt Duck Typing: “Wenn es wie eine Ente geht und wie eine Ente quakt, ist es eine Ente.” Objekte müssen nicht von derselben Klasse erben. Es genügt, wenn sie die erwarteten Methoden besitzen.

class Hund:
    def gib_laut(self):
        return "Wuff!"

class Katze:
    def gib_laut(self):
        return "Miau!"

# Polymorphie durch Duck Typing
def tier_geraeusch(tier):
    print(tier.gib_laut())

tier_geraeusch(Hund())   # Wuff!
tier_geraeusch(Katze())  # Miau!

Praxisbeispiel: Plugin-System

Ein klassisches Anwendungsbeispiel für Polymorphie ist ein Plugin-System. Der Hauptcode definiert eine Schnittstelle, und verschiedene Plugins implementieren diese auf ihre eigene Weise:

// Plugin-Interface
interface ExportPlugin {
    String getFormat();
    void exportiere(Dokument dok);
}

// Konkrete Plugins
class PDFExport implements ExportPlugin {
    @Override
    public String getFormat() { return "PDF"; }
    
    @Override
    public void exportiere(Dokument dok) {
        // PDF-spezifische Logik
    }
}

class CSVExport implements ExportPlugin {
    @Override
    public String getFormat() { return "CSV"; }
    
    @Override
    public void exportiere(Dokument dok) {
        // CSV-spezifische Logik
    }
}

// Verwendung - der Code kennt nur das Interface
class Anwendung {
    private List<ExportPlugin> plugins = new ArrayList<>();
    
    public void registriere(ExportPlugin plugin) {
        plugins.add(plugin);
    }
    
    public void exportiereAlle(Dokument dok) {
        for (ExportPlugin plugin : plugins) {
            plugin.exportiere(dok);  // Polymorpher Aufruf
        }
    }
}

Neue Export-Formate können hinzugefügt werden, ohne den Code der Anwendung zu ändern. Das ist die Stärke von Polymorphie: Offen für Erweiterung, geschlossen für Änderung (Open/Closed-Prinzip).

Polymorphie in der IT-Praxis

Polymorphie ist kein abstraktes Konzept, sondern begegnet dir in nahezu jedem objektorientierten Softwareprojekt. Wer als Fachinformatiker für Anwendungsentwicklung arbeitet, wird Polymorphie täglich einsetzen. Sei es bei der Arbeit mit Frameworks, beim Implementieren von Design Patterns oder beim Testen mit Mock-Objekten.

Prüfungsbezug

Passt zu deiner Prüfungsvorbereitung

Wenn dir dieser Begriff in Aufgaben, Projektdokumentation oder Fachgespräch begegnet, ordne ihn direkt in den Prüfungsstoff ein.