Vererbung (Inheritance)
In dieser Lerneinheit entdeckst du das zentrale OOP-Konzept der Vererbung und lernst, wie du Klassenhierarchien aufbaust, um Code effizient wiederzuverwenden. Du verstehst, wie Eigenschaften und Methoden von einer Basisklasse an ihre Kindklassen vererbt werden und wie du dieses Prinzip in der Praxis für die Entwicklung wartbarer Software einsetzt. Durch praktische Beispiele erfährst du, wie Vererbung dir hilft, redundanten Code zu vermeiden und deine Softwarearchitektur flexibel zu gestalten.
Einführung
Du arbeitest an einer Software für eine Fahrzeugverwaltung. Zunächst programmierst du eine Klasse für Autos mit Eigenschaften wie maxGeschwindigkeit, anzahlTüren und Methoden wie beschleunigen(). Dann sollst du eine Klasse für Motorräder hinzufügen.
Wenn du den gesamten Code für jede Fahrzeugart neu schreibst, hast du massiv duplizierten Code. Änderungen an gemeinsamen Funktionen müssen überall angepasst werden.

Vererbung (Inheritance) löst dieses Problem, indem gemeinsame Eigenschaften und Methoden in einer Basisklasse definiert werden. Spezialisierte Klassen erben diese und fügen nur ihre eigenen Besonderheiten hinzu.
In dieser Lerneinheit lernst du, wie Vererbung funktioniert, wie du Klassenhierarchien aufbaust und wie du Methoden in abgeleiteten Klassen überschreibst.
Lernziele
Nach dieser Lerneinheit kannst du:
- Das Konzept der Vererbung erklären und ihre Vorteile benennen
- Klassenhierarchien mit Basis- und abgeleiteten Klassen aufbauen
- Den Unterschied zwischen Einfach- und Mehrfachvererbung erklären
- Methoden in abgeleiteten Klassen überschreiben (Overriding)
- Den protected-Modifikator im Kontext von Vererbung einsetzen
Überleitung
Vererbung ist eines der mächtigsten Prinzipien der objektorientierten Programmierung. Es ermöglicht Code-Wiederverwendung und schafft klare Beziehungen zwischen Klassen.
Wir beginnen mit der grundlegenden Frage: Was genau ist Vererbung und warum ist sie so zentral für OOP?
Was ist Vererbung?
Vererbung (Inheritance) ist ein fundamentaler Mechanismus in der objektorientierten Programmierung. Eine Klasse kann Eigenschaften (Attribute) und Verhalten (Methoden) von einer anderen Klasse übernehmen.
Der Hauptvorteil: Gemeinsame Funktionalität muss nur einmal in einer Basisklasse geschrieben werden. Alle abgeleiteten Klassen erben diese automatisch.
Denk an eine Familie: Kinder erben Eigenschaften von ihren Eltern. In OOP erben Klassen von anderen Klassen.
Code-Wiederverwendung ist das zentrale Ziel: Anstatt denselben Code mehrfach zu schreiben, definierst du ihn einmal und lässt andere Klassen davon profitieren.
Klassenhierarchien
Eine Klassenhierarchie ist eine organisierte Struktur von Klassen, die ihre Beziehungen in Form eines Baums darstellt.
An der Wurzel steht eine allgemeine Klasse mit grundlegenden Eigenschaften. Spezialisierte Klassen erben von ihr und fügen eigene Besonderheiten hinzu.
Wichtige Begriffe:
- Basisklasse (Superclass, Elternklasse): Die Klasse, von der geerbt wird
- Abgeleitete Klasse (Subclass, Kindklasse): Die Klasse, die erbt
Beispiel-Hierarchie: Fahrzeug (Basisklasse) → Auto, Motorrad, LKW (abgeleitete Klassen)
Beispiel: Fahrzeug-Hierarchie (Teil 1)
Schauen wir uns an, wie Vererbung in der Praxis funktioniert. Wir bauen eine Fahrzeug-Hierarchie Schritt für Schritt auf.
Schritt 1: Basisklasse Fahrzeug
public class Fahrzeug {
protected int maxGeschwindigkeit;
}Das Attribut maxGeschwindigkeit ist protected deklariert. Bedeutung: Es ist in der Klasse selbst UND in allen abgeleiteten Klassen sichtbar, aber nicht von außen. Das ist wichtig für Vererbung.
Schritt 2: Methode hinzufügen
public class Fahrzeug {
protected int maxGeschwindigkeit;
public void beschleunigen(int geschwindigkeit) { // ← NEU
System.out.println("Fahrzeug beschleunigt");
}
}Die Methode beschleunigen() ist public - sie kann von überall aufgerufen werden. Sie definiert ein allgemeines Verhalten, das alle Fahrzeuge haben.
Beispiel: Fahrzeug-Hierarchie (Teil 2)
Schritt 3: Abgeleitete Klasse Auto
Jetzt erstellen wir eine spezialisierte Klasse, die von Fahrzeug erbt:
public class Auto extends Fahrzeug {
private int anzahlTüren;
public Auto(int maxGeschwindigkeit, int anzahlTüren) {
this.maxGeschwindigkeit = maxGeschwindigkeit;
this.anzahlTüren = anzahlTüren;
}
}Was passiert hier?
Das Schlüsselwort extends bedeutet “erbt von”. Die Klasse Auto erbt jetzt maxGeschwindigkeit und beschleunigen() von Fahrzeug.
Sie fügt ihr eigenes Attribut anzahlTüren hinzu.
Was bringt uns das?
Durch Vererbung müssen wir gemeinsamen Code wie maxGeschwindigkeit und beschleunigen() nicht mehrfach schreiben. Die Klasse Auto konzentriert sich nur auf das, was Autos speziell auszeichnet - die Anzahl der Türen. Wenn wir später weitere Fahrzeugarten wie Motorrad oder LKW hinzufügen, erben auch diese automatisch alle Eigenschaften von Fahrzeug. Das spart Code und macht Änderungen einfacher.
Einfachvererbung
Einfachvererbung bedeutet, dass eine Klasse von genau einer Basisklasse erbt. Dies ist die häufigste Form der Vererbung und wird in den meisten Programmiersprachen wie Java, C# und Python unterstützt.
Vorteile:
- Einfach zu verstehen: Klare Hierarchie von Eltern zu Kind
- Keine Mehrdeutigkeiten: Es gibt nur einen Vererbungspfad
- Wartbar: Änderungen in der Basisklasse wirken sich kontrolliert aus
Regel: In Java kann eine Klasse nur von einer Klasse erben, aber beliebig viele Interfaces implementieren.
Beispiel: Auto extends Fahrzeug - Auto erbt von genau einer Basisklasse.
Mehrfachvererbung
Mehrfachvererbung ermöglicht es einer Klasse, von mehreren Basisklassen gleichzeitig zu erben. Dies wird in Sprachen wie C++ unterstützt, aber nicht in Java oder C#.
Das Diamant-Problem:
Wenn zwei Basisklassen dieselbe Methode haben und eine Klasse von beiden erbt, entsteht eine Mehrdeutigkeit. Welche Version soll aufgerufen werden?
Beispiel in C++:
class Basisklasse1 {
public:
void methode1() { }
};
class Basisklasse2 {
public:
void methode2() { }
};
class Abgeleitete : public Basisklasse1, public Basisklasse2 {
public:
void kombiniert() {
methode1();
methode2();
}
};Wichtig: Mehrfachvererbung kann Komplexität erhöhen. Verwende sie nur wenn wirklich nötig.
Alternative: Interfaces
In Java und C# gibt es keine Mehrfachvererbung von Klassen. Stattdessen nutzen diese Sprachen Interfaces als Alternative.
Als Alternative zur Mehrfachvererbung nutzt Java Interfaces - dazu mehr in der nächsten Lerneinheit über Polymorphie.
Dort lernst du, wie Interfaces funktionieren und wann du sie einsetzt.
Überschreiben von Methoden: Konzept
Wenn eine Klasse von einer Basisklasse erbt, erbt sie nicht nur Attribute, sondern auch Methoden. Das Überschreiben (Overriding) erlaubt es, eine geerbte Methode in der abgeleiteten Klasse neu zu definieren.
Warum Methoden überschreiben?
- Spezifizierung: Die abgeleitete Klasse kann eine spezifischere Implementierung bereitstellen
- Erweiterung: Zusätzliche Logik vor oder nach dem Aufruf der Basisklassen-Methode
Wichtig: Overriding unterscheidet sich von Overloading. Overriding ändert das Verhalten einer geerbten Methode, Overloading erstellt mehrere Versionen einer Methode mit unterschiedlichen Parametern.
Überschreiben: Code-Beispiel
Schauen wir uns an, wie Overriding funktioniert:
class BaseClass {
void display() {
System.out.println("Anzeige von BaseClass");
}
}
class DerivedClass extends BaseClass {
@Override
void display() {
System.out.println("Angepasste Anzeige von DerivedClass");
}
}Erklärung des Codes
void display() {
System.out.println("Anzeige von BaseClass");
}Die Basisklasse definiert eine Methode display(). Bedeutung: Das ist die Standard-Implementierung.
@Override
void display() {
System.out.println("Angepasste Anzeige von DerivedClass");
}Die abgeleitete Klasse überschreibt diese Methode. Das @Override ist eine Annotation die dem Compiler sagt: Diese Methode soll eine geerbte Methode überschreiben. Bedeutung: Wenn die Signatur nicht passt, bekommst du einen Compiler-Fehler. Das verhindert Tippfehler.
Regeln für das Überschreiben
Beim Überschreiben von Methoden musst du bestimmte Regeln beachten:
| Regel | Beschreibung | Beispiel |
|---|---|---|
| Identische Signatur | Gleicher Name, gleiche Parameter, gleicher Rückgabetyp | void display() in Basis und Subklasse |
| Zugriffsrechte | Nicht restriktiver als Basisklasse | Aus public kann nicht private werden |
| Kovarianter Rückgabetyp | Kann Unterklasse des Basisklassen-Rückgabetyps sein | Basis gibt Fahrzeug zurück, Subklasse kann Auto zurückgeben |
| Static-Methoden | Können nicht überschrieben werden | static-Methoden gehören zur Klasse, nicht zum Objekt |
Wichtig: Die @Override-Annotation prüft, ob diese Regeln eingehalten werden. Compiler-Fehler helfen, Fehler früh zu erkennen.
Der protected-Modifikator
Der protected-Modifikator spielt bei Vererbung eine wichtige Rolle. Wie du in der Lerneinheit über Klassen und Objekte gelernt hast, steuern Zugriffsmodifikatoren, wer auf Attribute und Methoden zugreifen kann.
protected bedeutet:
- Zugriff innerhalb der eigenen Klasse
- Zugriff in allen abgeleiteten Klassen (Subklassen)
- Kein Zugriff von außerhalb der Vererbungshierarchie
Wann protected nutzen?
Verwende protected für Attribute oder Methoden, die in abgeleiteten Klassen verwendet werden sollen, aber nicht öffentlich sein dürfen.
Beispiel: protected int maxGeschwindigkeit; in der Fahrzeug-Klasse erlaubt allen abgeleiteten Klassen wie Auto oder Motorrad den direkten Zugriff.
Wichtige Aspekte bei Vererbung
Bei der Arbeit mit Vererbung solltest du einige wichtige Aspekte beachten:
Vererbungshierarchien sorgfältig gestalten:
Halte deine Klassenhierarchien überschaubar. Zu tiefe Hierarchien machen den Code schwer wartbar.
Abstrakte Klassen als Vorlagen:
Abstrakte Klassen dienen als Vorlagen für abgeleitete Klassen und können keine Instanzen haben. Mehr dazu erfährst du in der nächsten Lerneinheit über Polymorphie.
Vererbung vs. Komposition:
Nicht immer ist Vererbung die beste Lösung. Manchmal ist Komposition (eine Klasse enthält eine Instanz einer anderen) besser.
Zusammenfassung und Ausblick
Zusammenfassung
Vererbung löst ein zentrales Problem der Softwareentwicklung: Code-Duplikation. Gemeinsame Eigenschaften und Methoden werden in einer Basisklasse definiert und an spezialisierte Klassen vererbt. Das Schlüsselwort extends etabliert diese “ist-ein”-Beziehung: Ein Auto IST ein Fahrzeug.
Der protected-Modifikator ist der Schlüssel für Vererbung. Er ermöglicht abgeleiteten Klassen den Zugriff auf Attribute und Methoden der Basisklasse, ohne sie öffentlich zu machen. So bleibt die Kapselung gewahrt, während Vererbung funktioniert.
Methoden-Overriding ermöglicht Spezialisierung. Abgeleitete Klassen können geerbte Methoden neu definieren und an ihre Bedürfnisse anpassen. Die @Override-Annotation schützt vor Fehlern: Sie erzwingt, dass Signatur und Zugriffsrechte korrekt sind. Static-Methoden bleiben davon ausgenommen - sie gehören zur Klasse, nicht zu Objekten.
Die Wahl der Vererbungsart ist sprachabhängig. Java erlaubt nur Einfachvererbung von Klassen, um das Diamant-Problem zu vermeiden. C++ bietet Mehrfachvererbung, was mehr Flexibilität, aber auch Komplexität bringt. Java kompensiert dies durch Interfaces - mehr dazu in der nächsten Lerneinheit.
Ausblick
In der nächsten Lerneinheit lernst du Polymorphie kennen. Dort erfährst du, wie Overriding und Vererbung zusammenspielen, um flexiblen, erweiterbaren Code zu ermöglichen. Du verstehst dynamische Bindung, abstrakte Klassen und Interfaces im Detail.