Java Methoden überschreiben: Superclass-Verhalten anpassen
Was ist Methodenüberschreibung?
Im vorherigen Kapitel haben wir über Superclasses und Subclasses gesprochen. Wenn eine Klasse eine Methode von ihrer Superclass erbt, dann besteht die Möglichkeit, die Methode zu überschreiben, vorausgesetzt, sie ist nicht als final markiert.
Der Vorteil des Überschreibens ist: die Fähigkeit, ein Verhalten zu definieren, das spezifisch für den Subclass-Typ ist. Das bedeutet, eine Subclass kann eine Elternklassenmethode basierend auf ihren Anforderungen implementieren.
In objektorientierten Begriffen bedeutet Überschreiben, die Funktionalität einer bestehenden Methode zu überschreiben.
Beispiel
class Animal {
public void move() {
System.out.println("Animals can move");
}
}
class Dog extends Animal {
public void move() {
System.out.println("Dogs can walk and run");
}
}
public class TestDog {
public static void main(String args[]) {
Animal a = new Animal(); // Animal-Referenz und -Objekt
Animal b = new Dog(); // Animal-Referenz, aber Dog-Objekt
a.move(); // führt die Methode in der Animal-Klasse aus
b.move(); // führt die Methode in der Dog-Klasse aus
}
}
Ausgabe:
Animals can move
Dogs can walk and run
Im obigen Beispiel können Sie sehen, dass obwohl b vom Typ Animal ist, die move-Methode in der Dog-Klasse ausgeführt wird. Der Grund dafür ist: Zur Kompilierzeit wird die Prüfung am Referenztyp durchgeführt. Zur Laufzeit jedoch ermittelt die JVM den Objekttyp und führt die Methode aus, die zu diesem bestimmten Objekt gehört.
Daher kompiliert das Programm im obigen Beispiel korrekt, da die Animal-Klasse die Methode move hat. Zur Laufzeit führt es die methode aus, die spezifisch für dieses Objekt ist.
Betrachten Sie das folgende Beispiel:
Beispiel: Kompilierfehler bei Zugriff auf Subclass-spezifische Methode
class Animal {
public void move() {
System.out.println("Animals can move");
}
}
class Dog extends Animal {
public void move() {
System.out.println("Dogs can walk and run");
}
public void bark() {
System.out.println("Dogs can bark");
}
}
public class TestDog {
public static void main(String args[]) {
Animal a = new Animal(); // Animal-Referenz und -Objekt
Animal b = new Dog(); // Animal-Referenz, aber Dog-Objekt
a.move(); // führt die Methode in der Animal-Klasse aus
b.move(); // führt die Methode in der Dog-Klasse aus
b.bark(); // FEHLER!
}
}
Ausgabe (Kompilierfehler):
TestDog.java:26: error: cannot find symbol
b.bark();
^
symbol: method bark()
location: variable b of type Animal
1 error
Dieses Programm wirft einen Kompilierzeitfehler, da der Referenztyp b (Animal) keine Methode mit dem Namen bark hat.
Regeln für Methodenüberschreibung
- Die Argumentliste sollte genau dieselbe sein wie die der überschriebenen Methode.
- Der Rückgabetyp sollte derselbe oder ein Subtyp des in der ursprünglichen überschriebenen Methode in der Superclass deklarierten Rückgabetyps sein.
- Die Zugriffsebene kann nicht restriktiver sein als die der überschriebenen Methode. Beispiel: Wenn die Superclass-Methode
publicdeklariert ist, kann die überschreibende Methode in der Subclass wederprivatenochprotectedsein. - Instanzmethoden können nur überschrieben werden, wenn sie von der Subclass geerbt werden.
- Eine als
finaldeklarierte Methode kann nicht überschrieben werden. - Eine als
staticdeklarierte Methode kann nicht überschrieben werden, aber neu deklariert (re-declared) werden. - Wenn eine Methode nicht geerbt werden kann, dann kann sie nicht überschrieben werden.
- Eine Subclass im selben Paket wie die Instanz-Superclass kann jede Superclass-Methode überschreiben, die nicht als
privateoderfinaldeklariert ist. - Eine Subclass in einem anderen Paket kann nur die nicht-finalen Methoden überschreiben, die als
publicoderprotecteddeklariert sind. - Eine überschreibende Methode kann beliebige unchecked Exceptions werfen, unabhängig davon, ob die überschriebene Methode Exceptions wirft oder nicht. Die überschreibende Methode sollte jedoch keine checked Exceptions werfen, die neu oder breiter sind als die von der überschriebenen Methode deklarierten. Die überschreibende Methode kann engere oder weniger Exceptions werfen als die überschriebene Methode.
- Konstruktoren können nicht überschrieben werden.
Verwendung des super-Schlüsselworts
Beim Aufrufen einer Superclass-Version einer überschriebenen Methode wird das super-Schlüsselwort verwendet.
Beispiel
class Animal {
public void move() {
System.out.println("Animals can move");
}
}
class Dog extends Animal {
public void move() {
super.move(); // ruft die Superclass-Methode auf
System.out.println("Dogs can walk and run");
}
}
public class TestDog {
public static void main(String args[]) {
Animal b = new Dog(); // Animal-Referenz, aber Dog-Objekt
b.move(); // führt die Methode in der Dog-Klasse aus
}
}
Ausgabe:
Animals can move
Dogs can walk and run
Java
- Java Operatoren meistern: Typen, Syntax und praktische Beispiele
- Java-Schnittstellen meistern: Konzepte, Implementierung und Best Practices
- Java String length() Methode: String-Länge ermitteln (Beispiel)
- Java String.indexOf() meistern: Substrings finden & praktische Beispiele
- Java String.charAt(): Syntax, Rückgabetyp, Exceptions und praktisches Beispiel
- Java String compareTo() meistern: Syntax, Anwendungsfälle und praktische Beispiele
- Java String.contains() Methode: Substrings prüfen – praktische Beispiele
- Java String.endsWith(): String-Suffixe prüfen mit Beispielen
- Java String-Ersetzung meistern: replace(), replaceAll() und replaceFirst() erklärt
- Java static erklärt: Variablen, Methoden und Blöcke – Praxisbeispiele