„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.
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.
„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:“
|
|
|
|
|
|
„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:“
|
|
|
|
||
|
|
|
„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.“
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.“
GO TO FULL VERSION