„Hallo Amigo! Jetzt folgt ein Thema, von dem ich glaube, dass du es oft brauchen kannst. Ich spreche von der Vererbung.

Für den Uneingeweihten ist Programmieren wie Magie. Also lass mich mit einer Analogie beginnen…

Nehmen wir an, du seist ein Zauberer, der ein fliegendes Pferd erschaffen will. Du könntest versuchen, einen Pegasus zu beschwören. Aber da fliegende Pferde in der Natur nicht vorkommen, wirst du es wirklich schwer haben. Du hättest eine Menge Arbeit vor dir. Es wäre viel einfacher, mit einem Pferd anzufangen und ein paar Flügel heraufzubeschwören.

Vererbung. Vorteile der Vererbung - 1

In der Programmierung nennen wir diesen Vorgang „Vererbung“. Angenommen, du musst eine sehr komplexe Klasse schreiben. Du könntest eine Menge Zeit damit verbringen, den Code von Grund auf neu zu schreiben und dann langwierige Tests durchführen, um Fehler zu finden. Aber warum solltest du es auf die harte Tour machen? Viel besser ist es, erst einmal zu schauen, ob die gesuchte Klasse bereits existiert?

Nehmen wir an, du findest eine Klasse, die 80 % der benötigten Funktionalität implementiert. Du kannst den Code dann einfach in deine Klasse kopieren. Aber das hätte mehrere Nachteile:

1) Die gefundene Klasse könnte bereits in Bytecode kompiliert sein. Möglicherweise hast du keinen Zugriff auf den Quellcode.

2) Vielleicht hast du auch den Quellcode der Klasse, aber die Firma, für die du arbeitest, könnte auf ein paar Milliarden verklagt werden, wenn du auch nur 6 Zeilen des Codes eines anderen benutzt. Und dann werden sie dich verklagen.

3) Das führt zu einer unnötigen Duplizierung von einer Menge Code. Und wenn der Autor der anderen Klasse einen Fehler findet und ihn behebt, ist der Fehler bei dir immer noch vorhanden.

Es gibt eine elegantere Lösung, die keine rechtliche Erlaubnis für die Nutzung des Codes der ursprünglichen Klasse erfordert. In Java kannst du einfach die andere Klasse als Elternklasse deiner Klasse deklarieren. Das entspricht dem Hinzufügen des Codes dieser Klasse zu deiner eigenen Klasse. Alle Daten und Methoden der Elternklasse erscheinen in deiner Klasse. Zum Beispiel kannst du von einem „Pferd“ erben, „Flügel“ hinzufügen und so einen „Pegasus“ erhalten.

Vererbung. Vorteile der Vererbung - 2

„Interessant. Bitte erzähl mir mehr.“

„Vererbung kann auch in anderen Fällen sinnvoll eingesetzt werden. Angenommen, du hast zehn Klassen, die sich sehr ähnlich sind. Sie haben übereinstimmende Daten und Methoden. Du könntest eine spezielle Basisklasse erstellen, die Daten (und die zugehörigen Methoden) in die Basisklasse verschieben und diese zehn Klassen von ihr erben lassen. Mit anderen Worten, für jede Klasse gibst du an, dass sie eine Elternklasse hat, die auch Basisklasse genannt wird.“

„So wie sich die Vorteile der Abstraktion erst in Verbindung mit der Kapselung wirklich offenbaren, so werden die Vorteile der Vererbung durch den Polymorphismus offenbar. Aber davon erzähle ich dir morgen. Heute sehen wir uns noch ein paar Beispiele für die Vererbung an.“

„Nehmen wir an, wir wollen ein Schachprogramm schreiben. Dann brauchen wir Klassen für die Schachfiguren. Welche Klassen würdest du vorschlagen, Amigo?“

„König, Dame, Läufer, Springer, Turm und Bauer.“

„Sehr schön. Genau so ist es.“

„Und welche Daten sollten in diesen Klassen gespeichert werden?“

„Die Position auf dem Schachbrett (x und y) und der Wert. Schließlich sind einige Figuren wertvoller als andere.“

„Und was sind die Unterschiede zwischen diesen Klassen?“

„Sie unterscheiden sich darin, wie sie die Figuren bewegen. In ihrem Verhalten.“

„Ja. Man könnte sie als Klassen wie folgt definieren:“

class King
{
int x;
int y;
int worth;
void kingMove()
{
//code that defines,
//how the king moves
}
}
class Queen
{
int x;
int y;
int worth;
void queenMove()
{
//code that defines,
//how the queen moves
}
}
class Rook
{
int x;
int y;
int worth;
void rookMove()
{
//code that defines,
//how the rook moves
}
}
class Knight
{
int x;
int y;
int worth;
void knightMove()
{
//code that defines,
//how the knight moves
}
}
class Bishop
{
int x;
int y;
int worth;
void bishopMove()
{
//code that defines,
//how the bishop moves
}
}
class Pawn
{
int x;
int y;
int worth;
void pawnMove()
{
//code that defines,
//how the pawn moves
}
}

„Ja, genau so würde ich es auch schreiben.“

„Aber sieh dir an, wie du mit der Vererbung weniger Code schreiben könntest. Wir können identische Methoden und Daten in eine gemeinsame Klasse verschieben. Nennen wir sie ChessItem. Es ist nicht sinnvoll, ChessItem-Objekte zu erstellen, da sie keiner Schachfigur entsprechen. Aber die Klasse wäre extrem hilfreich:“

class King extends ChessItem
{
void kingMove()
{
//code that defines,
//how the king moves
}
}
class Queen extends ChessItem
{
void queenMove()
{
//code that defines,
//how the queen moves
}
}
class Rook extends ChessItem
{
void rookMove()
{
//code that defines,
//how the rook moves
}
}
 class ChessItem
{
int x;
int y;
int worth;
}
 
class Knight extends ChessItem
{
void knightMove()
{
//code that defines,
//how the knight moves
}
}
class Bishop extends ChessItem
{
void bishopMove()
{
//code that defines,
//how the bishop moves
}
}
class Pawn extends ChessItem
{
void pawnMove()
{
//code that defines,
//how the pawn moves
}
}

„Sehr interessant!“

„Absolut! Besonders groß ist der Nutzen bei Projekten mit tausenden von verschiedenen Objekten und hunderten von Klassen. Richtig gewählte Klassen können in diesem Fall nicht nur die Logik deutlich vereinfachen, sondern auch den benötigten Code um den Faktor zehn reduzieren.“

„Was muss man also tun, um eine Klasse zu vererben?“

„Nach der Deklaration einer Klasse verwenden wir das Schlüsselwort ‚extends‘, gefolgt vom Namen der Elternklasse. Du kannst nur von einer Klasse erben.“

Vererbung. Vorteile der Vererbung - 3

Das Bild zeigt eine „Kuh“, die von einem „Schwein“ geerbt hat. Das „Schwein“ erbt vom „Huhn“, und das „Huhn“ erbt vom „Ei“. Jede Klasse hat nur eine Elternklasse! Eine solche Vererbung ist nicht immer logisch. Wenn man nur ein Schwein hat, aber eigentlich eine Kuh braucht, können Programmierer oft nicht dem Wunsch widerstehen, aus dem „Schwein“ eine „Kuh“ zu machen.

„Aber was ist, wenn ich von zwei Klassen erben will? Kann ich dann irgendetwas tun?!“

„Eigentlich nicht. Java-Klassen unterstützen keine Mehrfachvererbung der Implementierung: Eine Klasse kann nur eine einzige Elternklasse haben. Es gibt aber eine Mehrfachvererbung des Typs, d.h. eine Klasse kann mehr als ein Interface implementieren. Das mildert das Problem ein wenig.“

„Verstehe. Und was ist ein Interface?“

„Ich erzähle dir morgen von Interfaces. Lass uns fürs Erste tiefer in die Vererbung einsteigen.“