Vererbung
In den vorhergehenden Lektionen wurde die Vererbung mehrfach erwähnt. In der Java-Sprache können Klassen von anderen Klassen abgeleitet werden, wodurch Felder und Methoden von diesen Klassen geerbt werden.
Mit Ausnahme von
Object
, das keine Oberklasse hat, hat jede Klasse eine und nur eine direkte Oberklasse (Einzelvererbung). In Ermangelung einer anderen expliziten Oberklasse ist jede Klasse implizit eine Unterklasse von Object
. Klassen können von Klassen abgeleitet werden, die von Klassen abgeleitet sind, die von Klassen abgeleitet sind, und usw. und letztendlich von der obersten Klasse abgeleitet,
Object
. Eine solche Klasse soll von allen Klassen in der Vererbungskette abstammen, die bis Object
zurückreichen. Die Idee der Vererbung ist einfach, aber leistungsstark: Wenn Sie eine neue Klasse erstellen möchten und bereits eine Klasse vorhanden ist, die einen Teil des gewünschten Codes enthält, können Sie Ihre neue Klasse aus der vorhandenen Klasse ableiten . Auf diese Weise können Sie die Felder und Methoden der vorhandenen Klasse wiederverwenden, ohne sie selbst schreiben (und debuggen!) Zu müssen.
Eine Unterklasse erbt alle Mitglieder (Felder, Methoden und verschachtelte Klassen) von seine Superklasse. Konstruktoren sind keine Mitglieder, daher werden sie nicht von Unterklassen geerbt, aber der Konstruktor der Oberklasse kann aus der Unterklasse aufgerufen werden.
Die Hierarchie der Java-Plattformklassen
Die Object
, die im Paket java.lang
definiert ist, definiert und implementiert das Verhalten aller Klassen – einschließlich der von Ihnen geschriebenen. In der Java-Plattform leiten sich viele Klassen direkt von Object
ab, andere Klassen von einigen dieser Klassen usw. und bilden eine Hierarchie von Klassen.
Alle Klassen in der Java-Plattform sind Nachkommen des Objekts
An der Spitze der Hierarchie steht Object
für die allgemeinste aller Klassen. Klassen am Ende der Hierarchie bieten ein spezielleres Verhalten.
Ein Beispiel für Vererbung
Hier ist der Beispielcode für eine mögliche Implementierung eines Bicycle
-Klasse, die in der Lektion „Klassen und Objekte“ vorgestellt wurde:
Eine Klassendeklaration für eine MountainBike
-Klasse, die eine Unterklasse von könnte folgendermaßen aussehen:
public class MountainBike extends Bicycle { // the MountainBike subclass adds one field public int seatHeight; // the MountainBike subclass has one constructor public MountainBike(int startHeight, int startCadence, int startSpeed, int startGear) { super(startCadence, startSpeed, startGear); seatHeight = startHeight; } // the MountainBike subclass adds one method public void setHeight(int newValue) { seatHeight = newValue; } }
MountainBike
erbt Alle Felder und Methoden von Bicycle
und fügt das Feld seatHeight
und eine Methode zum Festlegen hinzu. Mit Ausnahme des Konstruktors ist es so, als hätten Sie eine neue MountainBike
-Klasse mit vier Feldern und fünf Methoden von Grund auf neu geschrieben. Sie mussten jedoch nicht die ganze Arbeit erledigen. Dies wäre besonders wertvoll, wenn die Methoden in der Klasse Bicycle
komplex wären und das Debuggen viel Zeit in Anspruch genommen hätte.
Was Sie in einer Unterklasse tun können
Eine Unterklasse erbt alle öffentlichen und geschützten Mitglieder ihres übergeordneten Elements, unabhängig davon, in welchem Paket sich die Unterklasse befindet. Wenn sich die Unterklasse im selben Paket wie ihre befindet Eltern, es erbt auch die paketprivaten Mitglieder des Elternteils. Sie können die geerbten Mitglieder unverändert verwenden, ersetzen, ausblenden oder durch neue Mitglieder ergänzen:
- Die geerbten Felder können kann wie alle anderen Felder direkt verwendet werden.
- Sie können ein Feld in der Unterklasse mit demselben Namen wie das in der Oberklasse deklarieren und so ausblenden (nicht empfohlen).
- Sie können neue Felder in der Unterklasse deklarieren, die nicht zur Oberklasse gehören.
- Die geerbten Methoden können direkt wie sie sind verwendet werden.
- Sie können eine neue Instanzmethode in die Unterklasse schreiben Unterklasse das hat dieselbe Signatur wie die in der Oberklasse und überschreibt diese.
- Sie können eine neue statische Methode in die Unterklasse schreiben, die dieselbe Signatur wie die in der Oberklasse hat, wodurch sie ausgeblendet wird.
- Sie können neue Methoden in der Unterklasse deklarieren, die nicht zur Oberklasse gehören.
- Sie können einen Unterklassenkonstruktor schreiben, der den Konstruktor der Oberklasse entweder implizit oder mithilfe des Schlüsselworts
super
.
In den folgenden Abschnitten dieser Lektion werden diese Themen erläutert.
Private Mitglieder in einer Superklasse
Eine Unterklasse erbt nicht die private
-Mitglieder ihrer übergeordneten Klasse. Wenn die Oberklasse jedoch über öffentliche oder geschützte Methoden für den Zugriff auf ihre privaten Felder verfügt, können diese auch von der Unterklasse verwendet werden.
Eine verschachtelte Klasse hat Zugriff auf alle privaten Mitglieder ihrer einschließenden Klasse – sowohl Felder als auch Methoden. Daher hat eine öffentliche oder geschützte verschachtelte Klasse, die von einer Unterklasse geerbt wurde, indirekten Zugriff auf alle privaten Mitglieder der Oberklasse.
Casting-Objekte
Wir haben gesehen, dass ein Objekt von der ist Datentyp der Klasse, aus der es instanziiert wurde. Wenn wir beispielsweise
public MountainBike myBike = new MountainBike();
schreiben, ist myBike
vom Typ MountainBike
.
MountainBike
stammt von Bicycle
und Object
. Daher ist eine MountainBike
eine Bicycle
und auch eine Object
, und das kann sein Wird überall dort verwendet, wo Bicycle
oder Object
Objekte benötigt werden.
Das Gegenteil ist nicht unbedingt der Fall: eine Bicycle
kann eine MountainBike
sein, ist aber nicht unbedingt erforderlich. Ebenso kann eine Object
eine sein Bicycle
oder MountainBike
, aber es ist nicht unbedingt erforderlich.
Casting zeigt die Verwendung eines Objekts von einem Typ anstelle eines anderen Typs unter den Objekten, die durch Vererbung und Implementierungen zulässig sind. Wenn wir beispielsweise
Object obj = new MountainBike();
schreiben, ist obj
beide ein Object
und eine MountainBike
(bis obj
ein anderes Objekt zugewiesen wird, das kein MountainBike
). Dies wird als implizites Casting bezeichnet.
Wenn wir andererseits
MountainBike myBike = obj;
schreiben, würden wir dies tun Es wird ein Fehler zur Kompilierungszeit angezeigt, da obj
dem Compiler nicht als MountainBike
bekannt ist. Wir können dem Compiler jedoch mitteilen, dass wir versprechen, obj
durch explizites Casting eine MountainBike
zuzuweisen:
MountainBike myBike = (MountainBike)obj;
Diese Umwandlung fügt eine Laufzeitprüfung ein, dass obj
eine MountainBike
, damit der Compiler sicher annehmen kann, dass obj
eine MountainBike
ist. Wenn obj
zur Laufzeit keine MountainBike
ist, wird eine Ausnahme ausgelöst.
instanceof
. Dies kann Sie vor einem Laufzeitfehler aufgrund einer falschen Besetzung bewahren. Beispiel:
if (obj instanceof MountainBike) { MountainBike myBike = (MountainBike)obj;}
Hier überprüft der Operator instanceof
, ob obj
bezieht sich auf eine MountainBike
, damit wir die Umwandlung mit dem Wissen vornehmen können, dass keine Laufzeitausnahme ausgelöst wird.