Skip to main content

Java Vererbung bei Konstruktoren – Besonderheiten und Probleme

Klassen sind Baupläne für Java Objekte.
Java Konstruktoren sind ganz konkrete Baupläne für deine Objekte.

In einen der letzten Beiträge zur Java Vererbung, habe ich dir gezeigt – wie du polymorphe Arrays anlegst.
Dazu hatten wir das Beispiel mit den Kleidungsstücken.

Spinnen wir dieses Beispiel einfach mal weiter und erstellen jetzt Hosen.
Also dann – Nehmen wir einmal an, du willst eine Hose bauen bzw. ein Hosen-Objekt mit Java erstellen.

Wie machst du das?
Ganz klar. Zuerst eine Java Klasse für Hosen anlegen.
Und dann in dieser oder einer anderen Java Klasse heraus – Objekte der Klasse „Hosen“ erstellen.

Java Vererbung Konstruktoren Klassen Objekte anlegen

Die Klasse bildet somit den Bauplan für Hosen.
Sobald du den Konstruktor zur Hose aufrufst, wird tatsächlich eine Hose erstellt.

Man kann sagen:

„Der Konstruktor konstruiert dann die Hose anhand des Bauplanes der entsprechenden Java Klasse.“

Aber …..
Bei der Vererbung entsteht allerdings ein Problem mit dem Konstruktor.
Nicht mit jedem. Aber einige Konstruktoren funktionieren bei der Vererbung einfach nicht mehr.

Welche Konstruktoren dies sind und wie du dieses Problem löst – das zeige ich dir in diesem Artikel.

Aber wiederholen wir erst noch ein bisschen.

Java Konstruktoren am einfachen Beispiel.

Ich bleibe bei dem Beispiel mit den Hosen und lege dazu eine Klasse an.

public class Hose {

}

Außerdem lege ich eine Klasse für „Jacken“ an.

public class Jacke {

}

Und noch eine Klasse „HosenJackenSimulator“, welche die main-Methode für den Programmstart enthält.

public class HoseJackeSimulator {

	public static void main(String[] args) {
		
	}
}

Jetzt kann ich in der Starterklasse Objekte anlegen.

public class HoseJackeSimulator {

	public static void main(String[] args) {
		Hose jeans = new Hose (); //neues Hosenobjekt
		Jacke windJacke = new Jacke (); //neues Jackenobjekt
	}
}

Diese machen bis jetzt noch gar nichts, da in den entsprechenden Klasse „Hose“ und „Jacke“ noch nichts festgelegt wurde.

Also was könntest du nun mit Hosen und Jacken so machen?
Vielleicht so etwas:

  • Hosen und Jacken haben eine bestimmte Größe – Instanzvariable vom Typ String
  • Hosen und Jacken haben einen Hersteller bzw. eine Marke – zweites Feld ebenfalls vom Typ String
  • Und noch eine Methode „gibInfos()“ welche dir die Informationen zu Jacken und Hosen auf der Konsole zurückgibt.

Also dann – gesagt, getan.
Hier ist die Hosenklasse mit den Instanzvariablen „marke“ und „groesse“, sowie der Instanzmethode „gibInfos“.

public class Hose {
	String marke;//Instanzvariable für Hosenmarken
	String groesse;//Instanzvariable für Hosengrößen

	void gibInfos() {
		System.out.println("Hose Marke:"+marke+" Größe:"+groesse);
	}
}

Analog dazu die Jackenklasse.

public class Jacke {
	String marke;//Instanzvariable für Jackenmarken
	String groesse;//Feld für Jackengröße

	void gibInfos() {
		System.out.println("Jacke Marke:"+marke+" Größe:"+groesse);
	}
}

Zurück in der Programmstartklasse „HosenJackenSimulator“ kannst du den Objektvariablen Werte zuweisen und die Methoden aufrufen.

public class HoseJackeSimulator {

	public static void main(String[] args) {
		Hose jeans = new Hose (); //neues Hosenobjekt
		Jacke windJacke = new Jacke (); //neues Jackenobjekt
		
		jeans.marke="HOSEN-MARKE";//Zuweisung des Hosen-Markennamens
		jeans.groesse="XL";//Zuweisung der Hosengröße
		jeans.gibInfos();//Rückgabe der Hoseninfos
		windJacke.marke="Jacken-Marke";
		windJacke.groesse="S";
		windJacke.gibInfos();
	}
}

Klicke auf „RUN“ und die beiden gibInfo-Methoden laufen, oder?

Bis jetzt ist hier eigentlich nichts Neues und nichts Ungewöhnliches.

Okay, dann bieten wir doch stattdessen einmal einen richtigen Konstruktor in der Hosenklasse an.

Bis jetzt haben wir nur den Default-Konstruktor aufgerufen.

Java Vererbung Default Konstruktor aufrufen

Dieser Default-Konstruktor ist der Standardkonstruktor, welche jede Klasse sowieso hat.
Aber meistens ist dieser nicht eindeutig bzw. spezifisch genug.

Denn bedenke….
Konstruktoren sind spezielle Konstruktionsanweisungen für die Objekte.
Und ein Default-Konstruktor ist in etwa so, wie eine Blanko-Konstruktionsanweisung.

Speziellere Konstruktionen sind immer präziser.
Also machen wir doch die Konstruktionsanweisung etwas präziser.

So kannst du einen echten Konstruktor in der Java Klasse implementieren.

Jede Hose muss zwingend bei der Konstruktion eine Größe haben.
Eigentlich logisch oder?

Also dann biete doch einen Konstruktor für Hosen an, welcher zwingend eine Größenangabe für Hosen einfordert.

Java Vererbung Konstruktor anpassen

Und wenn du dann Objekte erstellst, erfordert der Konstruktor von Anfang an – eine Größenangabe.
Java vererbung Konstruktoraufruf mit Parameter

Und hier der Code zur Hosenklasse:

public class Hose {
	String marke;
	String groesse;

	// Konstruktor erwartet einen String
	public Hose(String groesse) {

	}

	void gibInfos() {
		System.out.println("Hose Marke:" + marke + " Größe:" + groesse);
	}
}

Den Code in der Programmstartklasse kannst du erst einmal so lassen.

public class HoseJackeSimulator {

	public static void main(String[] args) {
		Hose jeans = new Hose (); //neues Hosenobjekt
		Jacke windJacke = new Jacke (); //neues Jackenobjekt
		
		jeans.marke="HOSEN-MARKE";//Zuweisung des Hosen-Markennamens
		jeans.groesse="XL";//Zuweisung der Hosengröße
		jeans.gibInfos();//Rückgabe der Hoseninfos
		windJacke.marke="Jacken-Marke";
		windJacke.groesse="S";
		windJacke.gibInfos();
	}
}

Okay nun klicke auf „RUN“ und starte das Java Programm.

Und läuft?
Nee – Es kommt zu einer Fehlermeldung, aber nur bei Hosen.
Die Jacken funktionieren weiterhin.

Java Konstruktor Compiler Fehler

Also was heißt das?
Sobald du einen echten Konstruktor in einer Java Klasse anbietest, funktioniert der Default Konstruktor nicht mehr.

Ganz klar.
Denn der Konstruktor soll schließlich einen ganz genauen Plan, zur Objekterstellung, vorgeben.
Und somit soll es dann auch keinen anderen Weg mehr geben.
Logisch, oder?

Der Ausweg würde darin bestehen, den Default-Konstruktor ebenfalls anzubieten und somit die Konstruktoren zu überladen.

Dieses Beispiel lief bis hierher komplett ohne Vererbung.
Jetzt stellen wir eine Vererbungslinie her und schauen uns dann die Konstruktoren an.

Also wie könnte die Vererbungslinie für Hosen und Jacken in diesem Java Programm aussehen?

Vielleicht Kleidung bzw. Kleidungsstücke?
Absolute Klarheit verschafft die „IST-ES-EINE-Methode“.

Ist die Hose ein Kleidungsstück? Ja
Und ist jede Hose ein Kleidungstück? – Ebenfalls ja.

Java Vererbung Tafel Klassen Vaterklassen

In unserem Vererbungsdesign könnte die Hose von einer Superklasse Kleidung erben.

Wie sieht es mit der Jacke aus?
Ist die Jacke ein Kleidungsstück? Ja
Und würde jede Jacke ein Kleidungsstück sein? Wieder ja.

Java Vererbungstafel Klassen Superklassen

Also auch Jacke könnte eine übergeordnete Vaterklasse „Kleidungsstück“ haben.

Somit könntest du eine neue Klasse, namens Kleidung, Kleidungsstück oder Klamotten erstellen.
Und diese wäre die Superklasse zu Hosen und Jacken.
Ich nenne diese „Kleidungsstueck“, da ich die Klasse „Kleidung“ schon einmal in einem anderen Beitrag verwendet habe.

public class KleidungsStueck {
	String groesse;//Kleidungstück enthält jetzt die Variable
	String marke;//Kleidungsstück enthält jetzt die Marke
	
	void gibInfos(){
		System.out.println("Kleidung Marke:" + marke + " Größe:" + groesse);
	}
}

Die Klasse „KleidungsStueck“ hat jetzt die Instanzvariablen zur Größe und zur Marke.
Somit musst du diese Variablen in den Kindklassen nicht mehr separat implementieren und sparst doppelten Code.

Nun kannst du mit dem Keywort extends, die Klassen „Hose“ und „Jacke“ erweitern.
Wie schon beschrieben, kannst du dir – die Instanzvariablen jetzt sparen.

public class Hose extends KleidungsStueck {

	void gibInfos() {
		System.out.println("Hose Marke:" + marke + " Größe:" + groesse);
	}
}

Die Instanzvariablen sind aufgrund der Vererbung aus der Superklasse „KleidungsStueck“ bekannt.

public class Jacke extends KleidungsStueck {

	void gibInfos() {
		System.out.println("Jacke Marke:"+marke+" Größe:"+groesse);
	}
}

Und auch die Jackenklasse besitzt bereits die Instanzvariablen der Superklasse „KleidungsStueck“.
Hier der Beweis:

public class HoseJackeSimulator {

	public static void main(String[] args) {
		Hose jeans = new Hose (); //neues Hosenobjekt
		Jacke windJacke = new Jacke (); //neues Jackenobjekt
		
		jeans.marke="HOSEN-MARKE";//Hosen besitzen die Variable aus der Superklasse
		jeans.groesse="XL";//Variable aus der Superklasse "Kleidungsstueck"
		jeans.gibInfos();//Methode aus der Hosen-Klasse
		windJacke.marke="Jacken-Marke";//Variable aus der Superklasse
		windJacke.groesse="S";//Variable aus der Superklasse
		windJacke.gibInfos();//Methode aus der Kindklasse "Jacke"
	}
}

Alles gut?

So und nun biete einmal einen richtigen Konstruktor in der Superklasse an.

Also dann.

public class KleidungsStueck {
	String groesse;
	String marke;
	
	void gibInfos(){
		System.out.println("Kleidung Marke:" + marke + " Größe:" + groesse);
	}
	
	public KleidungsStueck(String groesse) {

	}
}

Jetzt hat die Super-Klasse „KleidungsStueck“ wieder einen echten Konstruktor.
Und somit passt der Default-Konstruktor für beide Kindklassen nicht mehr.

Java Vererbung Konstruktor Probleme

Was heißt das jetzt?

Bei der Java Klassen Vererbung werden nur Methoden und Variablen vererbt.

Konstruktoren werden nicht automatisch von den Vater- in die Kindklasse weiter vererbt.

Was kannst du jetzt machen?
Na klar, in beiden Kindklassen wieder einen separaten Konstruktor einbauen.
Sie wie hier in der Hosenklasse.

Java-Vererbung-Konstruktor-Superklasse-überschreiben

Ganz schön frech, wie manche Klassen mit ihren Eltern umgehen.
Da wird einfach der Konstruktor überschrieben. 🙂
Aber probieren wir es einfach.
Java Vererbung Superklasse Konstruktor überschreiben

Und passt immer noch nicht.
Überlege doch mal…

Was bewirkt eigentlich der Konstruktor in der Superklasse?

Klar er erschafft ein Objekt aus der Superklasse, also ein Kleidungsstück.

Und was noch?
Immer wenn du ein Kleidungsstück anlegst, steckt dort schon automatisch eine Jacke oder eine Hose drin.
Erinnere dich bitte an die Fragen:

  • Ist jede Hose immer ein Kleidungsstück? – Ja
  • Und ist jede Jacke immer ein Kleidungsstück? -Ebenfalls ja.

Java vererbung implizite Vererbung

Das bedeutet auch:

  • Somit legst du implizit bei jedem Kleidungstück auch immer etwas an, welches alle Voraussetzungen für eine Hose oder Jacke erfüllt.
  • Es entscheidet sich dann später, was genau daraus wird.
  • Dies ist so gewollt, denn dadurch ist Java extrem flexibel.
    Stichwort: Polymorphie

Also musst du einen spezielleren Java Konstruktor für Hosen oder Jacken anlegen.
Dieser holt sich ein Objekt aus der Kleidungsstück-Klasse.
Und daraus macht er dann ein Hosen- oder Jackenobjekt.

Das Keywort Super bewirkt eine Vererbung der Java Konstruktoren.

Vererbung ist vielleicht nicht ganz richtig formuliert.
Aber das Keywort super zeigt auf den Konstruktor der Vaterklasse.

  • Es ruft den Konstruktor mit gleicher Parameterliste der Vaterklasse auf.
  • Es holt sich das unfertige Objekt nach dessen Bauplan (1 x Kleidung bitte).
  • Und vervollständigt es. (Ich mache aus der Kleidung eine Hose oder Jacke.)

Hier am Beispiel:

public class Jacke extends KleidungsStueck {

	void gibInfos() {
		System.out.println("Jacke Marke:"+marke+" Größe:"+groesse);
	}
	
	//Konstruktor mit Größe
	public Jacke (String groesse){
		super (groesse);//Aufruf des Konstruktors der Superklasse
	}
	
}

Was passiert hier genau?
Die Variable super zeigt jetzt auf den entsprechenden Konstruktor in der Oberklasse.

Java Vererbung Konstruktor Super Aufruf

Und wie geht es jetzt weiter?
Du kannst einen zweiten Konstruktor in der Superklasse anbieten.
So wie diesen hier:

public class KleidungsStueck {
	String groesse;
	String marke;
	
	void gibInfos(){
		System.out.println("Kleidung Marke:" + marke + " Größe:" + groesse);
	}
	//Konstruktor der Superklasse mit zwingender Größenangabe
	public  KleidungsStueck (String groesse){
		this.groesse=groesse;//Zuweisung der Größe
	}
	
	//Konstruktor der Elternklasse mit zwingender Markken- und Größenangabe
	public KleidungsStueck (String marke, String groesse){
		this.groesse=groesse;//Zuweisung der Größe
		this.marke=marke;//Zuweisung der Marke
	}

}

Dieser Konstruktor würde jetzt ein Objekt anlegen, welches bereits eine bestimmte „Kleider-Marke“ und eine bestimmte „Kleider-Größe“ voraussetzt.
Die Zuweisung der Werte machst du, über das this-Keywort.

Und jetzt musst du in der Kindklasse ebenfalls einen zweiten Konstruktor anlegen.
Dieser ruft dann wiederum mit dem Keywort super, den Konstruktor mit gewünschter Parameterliste auf.

Java Vererbung Super Konstruktoren Aufruf

Hier der Code der Jackenklasse.

public class Jacke extends KleidungsStueck {

	void gibInfos() {
		System.out.println("Jacke Marke:"+marke+" Größe:"+groesse);
	}
	
	//1. Konstruktor mit Größe
	public Jacke (String groesse){
		super (groesse);//Aufruf des Konstruktors der Superklasse
	}
	
	//2.Konstruktor mit Größe und Marke
	public Jacke (String groesse, String marke){
		super (marke, groesse);//Aufruf des zweiten Konstruktors der Superklasse
	}
	
}

Und der Java Code in der Hosenklasse.

public class Hose extends KleidungsStueck {

	void gibInfos() {
		System.out.println("Hose Marke:" + marke + " Größe:" + groesse);
	}

	// 1. Konstruktor mit Größe
	public Hose(String groesse) {
		super(groesse);// Aufruf des Konstruktors der Superklasse
	}

	//2. Konstruktor mit Größe und Marke
	public Hose(String groesse, String marke) {
		super (marke, groesse);// Aufruf des zweiten Konstruktors der Superklasse
	}
}

Und schließlich kannst du dann in der Programmstart-Klasse die entsprechenden Objekte anlegen.

public class HoseJackeSimulator {

	public static void main(String[] args) {
		Hose jeans = new Hose ("HOSEN-MARKE"); //neues Hosenobjekt - Aufruf Konstruktor 1
		Hose stoff = new Hose ("HOSEN_MARKE","XXL");//Aufruf Konstruktor 2
		
		Jacke windJacke = new Jacke ("Jacken-Marke","S"); //neues Jackenobjekt - Aufruf Konstruktor 2
		Jacke stoffJacke = new Jacke ("JACKENMARKE","L");//Aufruf mit Konstruktor 2
		
		
		jeans.gibInfos();//Methodenaufruf
		stoff.gibInfos();
		windJacke.gibInfos();
		stoffJacke.gibInfos();
	}
}

Klicke auf „RUN“ und du siehst, dass die Konstruktoren in den Kindklassen ordentlich funktionieren.

Wichtig beim Aufruf ist nur die Parameterliste des aufgerufenen Superklassen Konstruktors

Folgende Konstellation:

  • Konstruktor Kindklasse – 1 Parameter.
  • Ruft Konstruktor der Elternklasse mit zwei Parameter auf.

Auch das geht.
Wie hier in der modifizierten Hosen-Klasse.


public class Hose extends KleidungsStueck {

	void gibInfos() {
		System.out.println("Hose Marke:" + marke + " Größe:" + groesse);
	}

	// 1. Konstruktor mit nur einem Parameter Größe
	public Hose(String groesse) {
		super("",groesse);// Aufruf des Konstruktors der Superklasse mit zwei Parametern
   }
}

Die Anführungszeichen sind lediglich ein Platzhalter.
Natürlich kannst du dort auch deine Lieblingshosenmarke übergeben.
Somit wären alle Hosen von Anfang an, von der selben Marke.

Über den Parameter „groesse“ würdest du dann nur noch die jeweiligen Hosengrößen festlegen und fertig.

Wichtig ist nur…
Es spielt keine Rolle, wieviel Parameter der Kindklassenkonstruktor hat.
Er kann jeden Super-Konstruktor der Vaterklasse aufrufen.
Lediglich die Parameter, welche er nicht selbst übergeben bekommt, muss er als Platzhalter übergeben.

Hier nochmal ein Bild dazu.
Zwar ist der Code aus der Hosenklasse und das Bild aus der Jackenklasse.
Aber dies ist doch „Jacke wie Hose“ 🙂

Java Vererbung Super Konstruktor verschiedene Parameterlisten

Aber was bringt jetzt die ganze Java Vererbung bei den Konstruktoren?

Falls du schon einige Objekte mit verschiedenen Konstruktoren angelegt haben solltest, dann kennst du das schon.
Eigentlich erreichst du dies auch, indem du die Konstruktoren einfach überlädst.

Aber was denkt sich Java dabei, mit diesem super Keywort?
Deutlich wird es, wenn wir zusätzlichen Code oder Methodenaufrufe in die Konstruktorenrümpfe einfügen.

Was stell ich mir vor:
Jedes Mal, wenn ein neues Kleidungsobjekt (egal welches) angelegt wird, soll eine Meldung über die Anzahl aller Objekte erscheinen.
Die Kleidungsstücke sollen also gezählt werden.

Im Klartext:
Die Instanzen der jeweiligen Klassen müssen gezählt werden.
Aber nicht nur das. Hosen und Jacken sollen außerdem separat gezählt werden.

Und hier machen wir uns das Prinzip der internen Konstruktorenaufrufe zu Nutze.

Angenommen wir machen:

  • 2 Hosen
  • 2 Jacken
  • 2 einfache Kleidungstücke

Dann wurden bereits bei den Hosen – 2 mal die Hosen-Konstruktoren und 2 mal die Kleidungs-Konstruktoren aufgerufen.

Java Vererbung Konstruktoraufrufe Anzahl

Das heißt aber auch, dass die jeweiligen Konstruktorenrümpfe komplett durchlaufen werden.
Jedes Mal, wenn eine Hose erstellt wird:

  • wird zuerst der ganze Code für Kleidungsstücke durchlaufen.
  • Und danach der ganze Code für Hosen, welcher im Konstruktorrumpf der Hosenklasse steht.

Cool, oder?

Weiter gehts bei den Jacken.

Java Vererbung Anzahl Konstruktor Aufruf

Prinzip ist klar, oder?
Auch hier wird wieder 2-mal Kleidungscode und danach 2 mal Jackencode ausgeführt.

Und schließlich die letzten beiden einfachen Kleidungsobjekte.

Java Vererbung Anzahl Superkonstruktoren Aufrufe

Jetzt benötigst du doch eigentlich nur Variablen, welche in den jeweiligen Konstruktorrümpfen hochgezählt werden.
Falls du den Artikel zu Instanzen-Zählen verpasst hast, dann schau später hier nach.
Jetzt bleibe bitte erst einmal am Ball. 🙂

So lässt du die Variablen im Konstruktorrumpf hochzählen.

Okay, was brauchst du?
Klar eine Klassenvariable, welche die Kleidungsstücke zählt.
Und eine Konsolenausgabe, welche den Wert dieser Variablen zurückgibt.

Also muss im Rumpf der einzelnen Konstruktoren diese Variable bei jedem Aufruf um eins erhöht werden.
Und eine Bildschirmausgabe wird dann diesen Wert zurückgeben.

Hier die Kleidungsstückklasse:

public class KleidungsStueck {
	String groesse;
	String marke;
	static int anzahlKleidungsStuecke;//zählt die Kleidungstücke
	
	void gibInfos(){
		System.out.println("Kleidung Marke:" + marke + " Größe:" + groesse);
	}
	//Konstruktor der Superklasse mit zwingender Größenangabe
	public  KleidungsStueck (String groesse){
		this.groesse=groesse;
		anzahlKleidungsStuecke=anzahlKleidungsStuecke+1;//bei jedem Aufruf um 1 erhöht
		System.out.println("Kleidungsstücke:"+anzahlKleidungsStuecke);//Konsolenausgabe
	}
	
	//Konstruktor der Elternklasse mit zwingender Marken- und Größenangabe
	public KleidungsStueck (String marke, String groesse){
		this.groesse=groesse;
		this.marke=marke;
		anzahlKleidungsStuecke=anzahlKleidungsStuecke+1;//Bei jedem Aufruf +1
		System.out.println("Kleidungstücke:"+anzahlKleidungsStuecke);//Konsolenausgabe
	}

}

Und die Programmstartklasse bleibt unverändert.

public class HoseJackeSimulator {

	public static void main(String[] args) {
		Hose jeans = new Hose ("HOSEN-MARKE"); //neues Hosenobjekt - Aufruf Konstruktor 1
		Hose stoff = new Hose ("HOSEN_MARKE","XXL");//Aufruf Konstruktor 2
		
		Jacke windJacke = new Jacke ("Jacken-Marke","S"); //neues Jackenobjekt - Aufruf Konstruktor 2
		Jacke stoffJacke = new Jacke ("JACKENMARKE","L");//Aufruf mit Konstruktor 2
		
		
		jeans.gibInfos();//Methodenaufruf
		stoff.gibInfos();
		windJacke.gibInfos();
		stoffJacke.gibInfos();
	}
}

Klicke einmal auf „RUN“ und was passiert?
Bei jedem Konstruktoren-Aufruf werden die Kleidungstücke nach oben gezählt.
Insgesamt befinden sich jetzt 4 Kleidungsstücke im Programm.

Okay, aber wir wollen schließlich auch wissen – wieviel Hosen und Jacken im Programm sind.

Wie machst du das jetzt?
Ich schrieb bereits, dass die Kindklassen-Konstruktoren aufgerufen werden und diese sich das Objekt aus der Vater- bzw. Superklasse holen.
Somit wurden bereits primär die Kindklassen-Konstruktoren aufgerufen und sekundär die Vaterklassen-Konstruktoren.

Und dies bedeutet, dass in den Konstruktorenaufrufen der Kindklassen ebenfalls Klassenvariablen hochgezählt werden müssen.
Hier die Jackenklasse mit Instanzzähler:

public class Jacke extends KleidungsStueck {
	static int anzahlJacken;// Klassenvariable zum Jacken-Zählen

	void gibInfos() {
		System.out.println("Jacke Marke:" + marke + " Größe:" + groesse);
	}

	// Konstruktor mit Größe
	public Jacke(String groesse) {
		super(groesse);
		anzahlJacken = anzahlJacken + 1;// Anzahl Jacken +1
		System.out.println("Davon sind Jacken:" + anzahlJacken);
	}

	// Konstruktor mit Größe und Marke
	public Jacke(String groesse, String marke) {
		super(groesse, marke);
		anzahlJacken = anzahlJacken + 1;// Anzahl Jacken + 1
		System.out.println("Davon sind Jacken:" + anzahlJacken);
	}

}

Und die Hosenklasse mit separaten Zähler:

public class Hose extends KleidungsStueck {
	static int anzahlHosen;//Zähler für Hosen

	void gibInfos() {
		System.out.println("Hose Marke:" + marke + " Größe:" + groesse);
	}

	// Konstruktor mit Größe
	public Hose(String groesse) {
		super(groesse);
		anzahlHosen=anzahlHosen+1;
		System.out.println("Davon Hosen:"+anzahlHosen);
	}

	// Konstruktor mit Größe und Marke
	public Hose(String groesse, String marke) {
		super (groesse, marke);
		anzahlHosen=anzahlHosen+1;
		System.out.println("Davon Hosen:"+anzahlHosen);
	}
}

Und die Programmstart-Klasse, diesmal auch mit unfertigen Kleidungsobjekten:

public class HoseJackeSimulator {

	public static void main(String[] args) {
		Hose jeans = new Hose ("HOSEN-MARKE"); 
		Hose stoff = new Hose ("HOSEN_MARKE","XXL");
		
		Jacke windJacke = new Jacke ("Jacken-Marke","S"); 
		Jacke stoffJacke = new Jacke ("JACKENMARKE","L");
		
		KleidungsStueck egalWas = new KleidungsStueck("L");//Kleidung, welche weder Hose noch Jacke ist
		KleidungsStueck wirdSchonWas = new KleidungsStueck("XL");
		
		
		jeans.gibInfos();
		stoff.gibInfos();
		windJacke.gibInfos();
		stoffJacke.gibInfos();
	}
}

Klicke ein letztes Mal auf „RUN“ und genieß die Show.
Es werden insgesamt 6 Kleidungsstücke gezählt, aber nur 2 Hosen und auch nur 2 Jacken.
Cool, oder. 🙂

Nochmal – Aufgrund dessen, dass du in den Kindklassen den Superkonstruktor aufrufst bekommst du:

  • alles was die Vaterklasse bei der Objekterstellung macht
  • und zusätzlich kannst du diesen Objekterstellungsprozess mit zusätzlichen Variablen oder Methodenaufrufen – für die Kids – erweitern.

Zusammenfassung:

  • Bei der Java Vererbung werden Instanzmethoden und Instanzvariablen von der Superklasse auf eine Kindklasse vererbt.
    Die Konstruktoren werden nicht automatisch mit vererbt.
  • Falls zwei Klassen in einer Vererbungshierarchie stehen und die Superklasse bereits einen Konstruktor implementiert hat, dann muss die Kindklasse mit dem Keywort super diesen Superkonstruktor aufrufen.
  • Außerdem kann die Kindklasse den Superkonstruktor der Elternklasse stets erweitern.