CodeGym /Kurse /JAVA 25 SELF /Verwendung von super: Aufruf des Konstruktors und von Met...

Verwendung von super: Aufruf des Konstruktors und von Methoden der Basisklasse

JAVA 25 SELF
Level 17, Lektion 2
Verfügbar

1. Verwendung von super zum Aufruf von Methoden der Basisklasse

Wenn Sie eine Unterklasse erstellen, kommt es manchmal vor, dass Sie auf Felder oder Methoden der Basisklasse zugreifen müssen – besonders, wenn Sie sie überschrieben oder „überschattet“ (versteckt) haben. Dafür gibt es in Java das spezielle Schlüsselwort super.

Als Analogie: super ist wie „Mama, hilf mir!“, wenn Sie in der Unterklasse ausdrücklich auf etwas zugreifen wollen, das in der Elternklasse definiert ist.

Stellen Sie sich vor, es gibt eine Klasse Animal mit der Methode eat(), die einfach "Das Tier frisst" ausgibt. Und in der Klasse Cat möchten Sie, dass die Katze erst etwas Eigenes tut (z. B. miaut) und danach trotzdem das Standard‑„Tier frisst“ ausführt. Genau hier hilft super.eat().

Wenn Sie in der Unterklasse eine Methode überschreiben, aber innerhalb dieser Methode dennoch die Implementierung aus der Basisklasse aufrufen möchten, verwenden Sie super.methodName().

Beispiel: Verhalten erweitern

class Animal {
    void eat() {
        System.out.println("Das Tier frisst");
    }
}

class Cat extends Animal {
    @Override
    void eat() {
        System.out.println("Die Katze schnuppert am Futter...");
        super.eat(); // ruft die Methode eat() aus Animal auf
        System.out.println("Die Katze schnurrt zufrieden");
    }
}

Wie funktioniert das?

  • Wenn eat() auf einem Objekt vom Typ Cat aufgerufen wird, wird zunächst der Code aus Cat.eat() ausgeführt, also die eigene Methode.
  • Innerhalb dieser Methode rufen wir explizit super.eat() auf, also die Implementierung aus der Elternklasse Animal.
  • So lässt sich zusätzliches Verhalten hinzufügen, ohne das „Elternverhalten“ zu vergessen.

Praxis: Einsatz in einer Anwendung

Angenommen, in unserer Lernanwendung gibt es die Basisklasse Animal und die Unterklassen Dog und Cat. Wir möchten, dass beim Füttern sowohl allgemeine Aktionen (z. B. Erhöhung der Sättigung) als auch spezifsche für jedes Tier ausgeführt werden.

class Animal {
    int satiety = 0;

    void eat() {
        satiety += 10;
        System.out.println("Das Tier frisst. Sättigung: " + satiety);
    }
}

class Dog extends Animal {
    @Override
    void eat() {
        System.out.println("Der Hund wedelt vor dem Fressen mit dem Schwanz");
        super.eat();
    }
}

Rufen Sie jetzt dog.eat() auf, sehen Sie beide Meldungen, und satiety erhöht sich korrekt.

2. Verwendung von super für den Zugriff auf Felder der Basisklasse

Wenn Sie in der Unterklasse ein Feld mit demselben Namen wie in der Elternklasse deklarieren, „überschattet“ es das Elternfeld. Manchmal müssen Sie auf das ursprüngliche Feld der Basisklasse zugreifen – dafür verwenden Sie super.fieldName.

Beispiel: Überschatten eines Feldes

class Animal {
    String name = "Tier";
}

class Cat extends Animal {
    String name = "Katze";

    void printNames() {
        System.out.println("Name aus Cat: " + name);
        System.out.println("Name aus Animal: " + super.name);
    }
}

Der Aufruf new Cat().printNames(); gibt aus:

Name aus Cat: Katze
Name aus Animal: Tier

In der Praxis wird das Überschatten von Feldern ohne zwingenden Grund nicht empfohlen, aber es ist gut, diese Möglichkeit zu kennen.

3. Aufruf des Konstruktors der Basisklasse über super(...)

Wie werden Objekte in einer Hierarchie erstellt?

Wenn Sie ein Objekt einer Unterklasse erstellen, wird zuerst der Konstruktor der Basisklasse aufgerufen und erst danach der Konstruktor der Unterklasse. Das ist nötig, damit alle Felder korrekt initialisiert werden, denn die Unterklasse „erbt“ einen Teil des Zustands von der Elternklasse.

Expliziter Aufruf des Konstruktors der Basisklasse

Wenn die Basisklasse einen parameterlosen Konstruktor hat, ist alles einfach: Java ruft ihn automatisch vor dem Konstruktor der Unterklasse auf. Hat die Elternklasse jedoch keinen parameterlosen Konstruktor, müssen Sie den passenden Konstruktor explizit über super(...) aufrufen.

Beispiel:

class Animal {
    String name;

    Animal(String name) {
        this.name = name;
        System.out.println("Tier erzeugt: " + name);
    }
}

class Cat extends Animal {
    Cat(String name) {
        super(name); // unbedingt! Es gibt keinen parameterlosen Animal()-Konstruktor
        System.out.println("Katze erzeugt: " + name);
    }
}

Der Aufruf new Cat("Murka") schreibt:

Tier erzeugt: Murka
Katze erzeugt: Murka

Wichtig: Der Aufruf des Elternkonstruktors über super(...) muss die erste Zeile des Unterklassenkonstruktors sein. Wenn Sie davor etwas schreiben, wird der Compiler reklamieren und Sie daran erinnern.

Nicht explizit aufgerufen?
Wenn die Elternklasse nur Konstruktoren mit Parametern hat und Sie diese nicht ausdrücklich über super(...) aufrufen, meldet der Compiler einen Fehler: "constructor Animal in class Animal cannot be applied to given types".

4. Nützliche Feinheiten

Wann verwendet man super?

Zum Erweitern statt zum Ersetzen des Verhaltens.
Manchmal möchten Sie das Verhalten einer Methode nicht vollständig ersetzen, sondern nur „erweitern“. Zum Beispiel etwas vor oder nach der Logik der Elternklasse hinzufügen. In solchen Fällen verwenden Sie super.methodName() im Körper der überschriebenen Methode.

Zur Initialisierung geerbter Felder.
Wenn die Elternklasse Felder hat, die zwingend initialisiert werden müssen (z. B. der Name eines Tiers), rufen Sie den passenden Elternkonstruktor mit den erforderlichen Parametern über super(...) auf.

Für den Zugriff auf verdeckte Felder/Methoden.
Wenn Sie aus irgendeinem Grund ein Feld oder eine Methode der Elternklasse überschattet haben und dennoch darauf zugreifen müssen, verwenden Sie super.fieldName oder super.methodName().

Einschränkungen und Besonderheiten der Verwendung von super

  • Den Aufruf des Elternkonstruktors über super(...) darf man nur im Konstruktor und nur als erste Zeile vornehmen.
  • Außerhalb des Unterklassenkonstruktors kann der Elternkonstruktor nicht aufgerufen werden.
  • Wenn super(...) nicht explizit aufgerufen wird, versucht Java den parameterlosen Elternkonstruktor aufzurufen (falls vorhanden).
  • Das Schlüsselwort super darf in statischen Methoden nicht verwendet werden – nur in Instanzmethoden und in Konstruktoren.
  • Wenn eine Methode oder ein Feld der Elternklasse private ist, hilft super nicht: Auf private Member gibt es keinen Zugriff.

5. Beispiele zur Festigung

Beispiel 1. Methode mit super erweitern

class Animal {
    void makeSound() {
        System.out.println("Das Tier macht ein Geräusch");
    }
}

class Dog extends Animal {
    @Override
    void makeSound() {
        super.makeSound(); // zuerst die Standardaktion ausführen
        System.out.println("Der Hund bellt: Wau-wau!");
    }
}

Beispiel 2. Aufruf des Konstruktors der Basisklasse

class Vehicle {
    String brand;

    Vehicle(String brand) {
        this.brand = brand;
        System.out.println("Fahrzeug: " + brand);
    }
}

class Car extends Vehicle {
    int year;

    Car(String brand, int year) {
        super(brand); // ruft den Elternkonstruktor auf
        this.year = year;
        System.out.println("Auto " + brand + ", Jahr: " + year);
    }
}
Car car = new Car("Toyota", 2023);
// Ausgabe:
// Fahrzeug: Toyota
// Auto Toyota, Jahr: 2023

Beispiel 3. Klassischer Fehler: super(...) vergessen

class Animal {
    String name;

    Animal(String name) {
        this.name = name;
    }
}

class Cat extends Animal {
    Cat() {
        // super(); // Fehler! Es gibt keinen parameterlosen Animal()-Konstruktor
        // super(name) muss explizit aufgerufen werden
        super("Namenlose Katze");
    }
}

6. Häufige Fehler bei der Arbeit mit super

Fehler Nr. 1: Aufruf von super(...) nicht in der ersten Zeile des Konstruktors.
Java verlangt strikt, dass der Aufruf des Elternkonstruktors über super(...) die erste Zeile des Unterklassenkonstruktors ist. Wenn Sie davor etwas tun (z. B. eine Meldung ausgeben), meldet der Compiler einen Fehler.

Fehler Nr. 2: Kein passender Konstruktor in der Elternklasse.
Wenn die Basisklasse keinen parameterlosen Konstruktor hat und Sie keinen anderen Konstruktor über super(...) aufrufen, kann der Compiler keinen Standardaufruf erzeugen und meldet einen Fehler.

Fehler Nr. 3: Versuch, über super auf private Member der Elternklasse zuzugreifen.
Das Schlüsselwort super gewährt keinen magischen Zugriff auf private Felder oder Methoden der Elternklasse. Was als private deklariert ist, bleibt für die Unterklasse unzugänglich.

Fehler Nr. 4: Überschatten von Feldern und Methoden ohne Verständnis.
Wenn Sie in der Unterklasse ein Feld oder eine Methode mit demselben Namen wie in der Elternklasse deklarieren und das vergessen, kann es zu unerwarteten Ergebnissen kommen. Denken Sie daran: In diesem Fall ist der Zugriff auf das Eltern‑Member nur über super möglich.

Fehler Nr. 5: Verwendung von super in einer statischen Methode.
In statischen Methoden darf super nicht verwendet werden, weil sie nicht zu einem konkreten Objekt gehören.

1
Aufgabe
JAVA 25 SELF, Level 17, Lektion 2
Gesperrt
Naturklänge: Vom Allgemeinen zum Besonderen 🐺
Naturklänge: Vom Allgemeinen zum Besonderen 🐺
1
Aufgabe
JAVA 25 SELF, Level 17, Lektion 2
Gesperrt
Fertigungsstraße: Montage von Transportmitteln und Fahrzeugen 🏭
Fertigungsstraße: Montage von Transportmitteln und Fahrzeugen 🏭
1
Aufgabe
JAVA 25 SELF, Level 17, Lektion 2
Gesperrt
Stammbaum des Haustiers: Namen auf verschiedenen Ebenen 🐾
Stammbaum des Haustiers: Namen auf verschiedenen Ebenen 🐾
1
Aufgabe
JAVA 25 SELF, Level 17, Lektion 2
Gesperrt
Universitätssystem: Registrierung von Studierenden 👨‍🎓
Universitätssystem: Registrierung von Studierenden 👨‍🎓
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION