Java Tutorial #20

Konstruktoren bei Vererbung

Wir wollen in diesem Kapitel etwas tiefer in die Materie der Vererbung vordringen und uns mit Konstruktoren im Zusammenhang mit Vererbung beschäftigen. Dieses Thema ist nicht ganz ohne, aber sehr wichtig. Halten Sie schon einmal den Kaffee bereit.

Stefan 02.03.2019

Infos zum Artikel

Kategorie Java
Autor Stefan
Datum 02.01.2019

Thema in Kurzform

  • Beim Instanziieren von Objekten werden alle Konstruktoren der Vererbungshierarchie "von unten nach oben " aufgerufen und von "oben nach unten" ausgeführt.
  • super() ruft den Konstruktor der unmittelbaren Superklasse explizit auf. Bei parameterlosen Konstruktoren wird super() vom Compiler automatisch ergänzt.

Wie funktionieren Konstruktoren bei Vererbung?

Über Konstruktoren in Java haben wir in vorherigen Kapitels zur Objektorientierung schon einiges gelernt. So hat jede Klasse mindestens einen Konstruktor und wenn kein Konstruktor explizit deklariert wurde, versucht Java, einen parameterlosen Standard-Konstruktor bereitzustellen. Richtig interessant wird das Thema aber erst jetzt in Zusammenhang mit Vererbung!

Folgende Grundregel ist der Kern für das Verständnis:

  • Wenn wir ein Objekt einer Unterklasse erzeugen, wird im Konstruktor dieser Unterklasse der Konstruktor der Oberklasse aufgerufen.

Verständlich wird das, wenn wir das einfach mal austesten. Hierzu lassen wir eine Unterklasse namens Siam von Katze erben, sodass wir folgende Vererbungshierarchie haben: Saeugetier <- Katze <- Siam. Anschließend erzeugen wir ein neues Siam-Objekt:

class Saeugetier {
    public Saeugetier(){
        System.out.println("Saeugetier-Konstruktor");
    }
}

class Katze extends Saeugetier {
    public Katze(){
        System.out.println("Katze-Konstruktor");
    }
}

 class Siam extends Katze {
    public Siam(){
        System.out.println("Siam-Konstruktor");
    }
}

class Playground {
   public static void main(String[] args){
       new Siam();
   }
}

Dieser Code erzeugt folgenden Print auf der Konsole:

Saeugetier-Konstruktor
Katze-Konstruktor
Siam-Konstruktor

Man sieht, dass alle Konstruktoren des Vererbungsbaums ausgeführt werden, wenn wir ein neues Unterklassen-Objekt erzeugen. Dieser Vorgang wird Konstruktorenverkettung genannt.

Genauer betrachtet passierte bei der Erzeugung des Siam-Objekts Folgendes:

  • Der Konstruktor von Siam ruft den Superklassenkonstruktor von Katze auf und dieser wiederum den Superklassenkonstruktor von Saeugetier.
  • Danach werden die Anweisungen in den einzelnen Konstruktoren "von oben nach unten" nacheinander ausgeführt.

super()

Um einen Superklassenkonstruktor aufzurufen, verwendet man das Schlüsselwort super(). In unserem Beispiel von eben war der Compiler aber so freundlich und hat super() für uns ergänzt.

super() wird nämlich automatisch ausgeführt, wenn wir es bei parameterlosen Konstruktoren nicht explizit ergänzen:

public Siam(){
    super(); //nicht nötig, wird automatisch ergänzt
    System.out.println("Siam-Konstruktor");
}

super() muss die erste Anweisung des Konstruktors der Unterklasse sein (Ausnahme siehe unten).

Konstruktoren mit Parametern

Und wie funktioniert das mit einem Superklassenkonstruktor, der Parameter hat? Ganz einfach: Dann muss der Konstruktor der Unterklasse ebenfalls entsprechende Parameter haben und diese dann mit super() an den Superklassekonstruktor weiterleiten.

Hier ein Beispiel:

class Katze extends Saeugetier {
    private String name;
    public Katze(String name){
        this.name = name;
    }
}


class Siam extends Katze {
    public Siam(String name){
        super(name); //Aufruf Superklassenkontruktor
    }
}


class Playground {
   public static void main(String[] args){
       new Siam("Simba");
   }
}

Unterschied this() und super()

Diese beiden Schlüsselwörter werden oft verwechselt. Deshalb hier in Kürze der Unterschied:

  • this() ruft einen anderen Konstruktor derselben Klasse auf (Konstruktor überladen).
  • super() ruft einen Konstruktor der direkten Superklasse auf.

Bei der Verwendung von this() und super() müssen folgende zwei Regeln eingehalten werden:

  • In einem Konstruktor dürfen this() und super() niemals zusammen verwendet werden..
  • this() bzw. super() muss immer die erste Anweisung in einem Konstruktor sein.

Sehen wir uns ein Beispiel an:

class Katze extends Saeugetier {
    private String name;
    public Katze(String name){
        this.name = name;
    }
}


class Siam extends Katze {
    //Konstruktor I
    public Siam(String name){
        super(name); //Aufruf Superklassenkonstruktor
    }

    //Konstruktor II
    public Siam(){
        this("Simba"); //Aufruf Konstruktor I
    }
}


class Playground {
   public static void main(String[] args){
       new Siam("Bailey");
       new Siam();
   }
}

Was geschieht hier? Die Klasse Siam bestitzt zwei Konstruktoren (Konstruktorüberladung). Damit können wir Siam-Objekte auf zwei verschiedene Arten erzeugen: Einmal mit einem String-Argument und einmal ohne.

Bei new Siam("Bailey"); wird Konstruktor I der Klasse Siam aufgerufen, der wiederum den Konstruktor der Superklasse Katze mitsamt dem "weitergereichten" Argument "Bailey" aufruft, also super("Bailey");

Bei der Objekterzeugung new Siam(); dagegen wird Konstruktor II aufgerufen. Dieser überladene Konstruktor verweist mit this("Simba") an Konstruktor I derselben Klasse. Dieser ruft dann wiederum den Superklassenkonstruktor mitsamt dem Argument "Simba" auf.

Konstruktoren bei Vererbung

Trainieren Sie ihre Konstruktoren-Skills

toString() Methode

Lernen Sie hier, wie Sie die toString() Methode korrekt einsetzen

Die Klasse Object

Erfahren Sie alles über die Mutter aller Klassen

FALCONBYTE.NET

Handmade with 🖤️

© 2018, 2019 Stefan E. Heller

Impressum | Datenschutz

facebook programmieren lernen twitter programmieren lernen youtube programmieren lernen