Um was geht es?
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.
Über Konstruktoren in Java haben wir in vorherigen Kapiteln 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:
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:
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).
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");
}
}
Diese beiden Schlüsselwörter werden oft verwechselt. Deshalb hier in Kürze der Unterschied:
Bei der Verwendung von this() und super() müssen folgende zwei Regeln eingehalten werden:
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 besitzt 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 Iderselben Klasse. Dieser ruft dann wiederum den Superklassenkonstruktor mitsamt dem Argument "Simba" auf.
Java Basics
[Java einrichten] [Variablen] [Primitive Datentypen] [Operatoren] [if else] [switch-case] [Arrays] [Schleifen]
Objektorientierung
[Einstieg] [Variablen ] [Konstruktor] [Methoden] [Rekursion] [Statische Member] [Initializer] [Pass-by-value] [Objektsammlungen] [Objektinteraktion] [Objekte löschen]
Klassenbibliothek
[Allgemeines] [String ] [Math] [Wrapper] [Scanner] [java.util.Arrays] [Date-Time-API]
Vererbung
[Einstieg Vererbung] [Konstruktoren bei Vererbung ] [Der protected Zugriffsmodifikator] [Abstrakte Klassen und Methoden] [Polymorphie in Java] [Typumwandlung] [Die Klasse Object] [Die toString()-Methode] [Objekte vergleichen] [Was ist ein Interface?]