Vererbung von Konstruktoren mit Parametern

nossek

Aktives Mitglied
Guten Tag,

was ich nicht verstehe:
Es heißt doch immer, bei der Vererbung werden alle Methoden und Attribute der Superklasse vererbt. Soweit klar, sinnvoll und toll!

Aber bei Konstruktoren ist das offensichtlich nicht so. Zwar: wenn die Superklasse einen parameterlosen Konstruktor hat, dann wird der auch bei der Erzeugung eines Objekts der abgeleiteten Klasse aufgerufen.

Hat die Superklasse aber einen Konstruktor mit Parametern, kann man diesen nicht ohne weiteres zur Erzeugung eines Objekts der abgeleiteten Klasse verwenden. Man muß offenbar in der Implementierung der abgeleiteten Klasse schreiben:
Java:
public AbgeleiteteKlasse(parameter){
         super(parameter);
}

Frage 1: Das erscheint mir als Anfänger etwas umständlich. Wäre es nicht einfacher, wenn auch Konstruktoren mit Parametern vererbt werden würden? (EDIT: wenn ich zB zu einer bestehenden Klasse einfach nur eine Methode hinzufügen möchte) Da aber die Java-Entwickler nicht auf den Kopf gefallen sind, muß ein Sinn dahinter stecken. Kann mir den jemand verraten?!

Frage 2: Wen ich in der abgeleiteten Klasse den Konstruktor mit Parametern auf oben genannte Weise implementiert habe, funktoniert der parameterlose Konstruktor nicht mehr "automatisch", ich muß ihn ebenfalls mit Verweis auf den der Superklasse implementieren. EDIT: Warum?

Ich hofe mich einigermaßen verständlich ausgedrückt zu haben (kann gerne Beispielcode posten falls etwas unklar ist). Vlt.ist es heute auch einfach zu warm zum Programmieren!

Danke, Gruß nossek
 
Zuletzt bearbeitet:
Konstruktoren gehören meines Wissens nach zum statischen Teil einer Klasse. Zum Zeitpunkt wo die Konstruktoren aufgerufen werden existiert das Objekt noch gar nicht, das heisst also das Objekt entsteht innerhalb des Konstruktors.
Und statische Methoden werden auch nicht vererbt wie nichtstatische Methoden.

PS: Ich hoffe, dass das so einigermassen stimmt ;-)

*Edit
Zur Frage 2:
Der Compiler erstellt einen Default-Konstruktor (der Default-Konstruktor ist parameterlos), wenn du selber keinen anderen definierst. Sobald du aber einen eigenen Konstruktor schreibst, so erzeugt der Compiler keinen Default-Konstruktor mehr. Somit musst du wieder einen eigenen parameterlosen Konstruktor schreiben.
 
Zuletzt bearbeitet:
Konstruktoren sind keine normalen Methoden, sie werden nicht vererbt und lassen sich nicht per Interface vereinbaren. Damit ähneln sie (wie von meinem Vorredner erwähnt) ein wenig statischen Methoden. Die Sonderstellung sieht man auch bei der Verwendung von Reflection, wo Methoden und Konstruktoren gesondert behandelt werden.

Ist die erste Zeile eines Konstruktors keine this() oder super()-Aufruf, wird automatische der parameterlose Konstruktor der Superklasse aufgerufen, bevor es weitergeht. Jede Klasse hat mindestens einen Konstruktur, wenn keiner angegeben wird, fügt der Compiler automatisch einen "leeren", parameterlosen Konstruktor ein.

1) Angenommen wir haben einen Konstruktor für Rechteck mit den Parametern Länge und Breite. Nun möchten wir eine Unterklasse Quadrat ableiten (streiten wir uns einmal nicht, ob das sinnvoll wäre oder nicht). Würde jetzt der Konstruktor einfach ungefragt vererbt, hätten wir einen ziemlich unbrauchbaren oder sogar gefährlichen Konstruktor in Quadrat, der eine falsche Initialisierung der Klasse zuließe. Ohne Vererbung haben wir dieses Problem nicht, können aber ohne weiteres zum Konstruktor der Superklasse deligieren, z.B.

Java:
class Quadrat extends Rechteck {
   public Quadrat(int laenge) {
      super(laenge, laenge);
   }
}

2) Das ist ein ähnliches Problem wie zuvor, der Default-Konstruktor kann unerwünscht sein. Wenn ich Felder in einem Objekt initialisieren muss, würde der Default-Konstruktor stattdessen ein uninitialisiertes Objekt zurückliefern. In Utility-Klassen wie java.lang.Math wird z.B. extra ein privater Konstruktor angelegt, um zu verhindern, dass irgendjemand ein Math-Objekt erzeugen kann (was nicht sinnvoll ist, da nur statische Methoden vorhanden sind). Der Programmierer hat also die Möglichkeit, sich bewußt gegen einen Default-Konstruktor zu entscheiden, und diese Möglichkeit ist wichtig.
 
Zuletzt bearbeitet:
Java sagt:

"Call to super must be first statement in constructor"

Das kommt daher, dass alle Klassen von Object erbenen:

public class Xyz = public class Xyz extends Object

Um ein Objekt erstellen zu können, muss der Konstruktor aufgerufen werden. Ist kein Konstruktor im Quelltext, dann erstellt der Compiler folgenden Code:

Java:
    public Xyz() {
        super();
    }

Ist nun in der Oberklasse ein anderer Konstruktor, dann ist das aber nicht möglich. Er weis schließlich nicht, was er übergeben soll. Im Zeifel kann man null übergeben, aber auf Nummer sichergehen ist immer besser 🙂
 
Zuletzt bearbeitet:
Danke Icarus2 + Landei

Wenn man selber in der Superklasse einen parameterlosen Konstruktor implementiert, nennt man den dann auch default-Konstruktor? Weil das funktioniert offenbar. Ein "new AbgeleiteteKlasse()" ruft ohne weiteres den parameterlosen Konstruktor der Superklasse auf.

Dieser Unterschied zwischen Klassenmethoden und Konstruktoren leuchtet mir schon ein. Trotzdem: wäre es nicht sehr bequem, wenn die abgeleiteten Klasse grundsätzlich den entsprechenden Konstruktor der Superklasse aufriefe (Abhängig von den Parametern...). Da muß es doch einen Grund geben daß die Sprache das nicht zulässt. Sorry fals ich etwas schwer von Begrif bin, wie gesagt: die Hitze...
 
Danke Ruzmanz.

Hmm, ich nehme es erstmal so hin, daß man das so machen muß. (Was bleibt mir auch anderes übrig!)

EDIT: Wie geht eigentlich durchstreichen? Würde obiges gerne steichen!

Melde mich gleich nochmals!
 
Zuletzt bearbeitet:
Sicher könnte man sich irgendwelche Regeln ausdenken, nach denen der Superkonstruktor aufgerufen wird, aber das war den Java-Machern wohl einfach zu gefährlich. Wenn ich z.B. einen Klasse Complex(real, imag) habe und dann eine Unterklasse PolarComplex(winkel, betrag) habe, wäre es natürlich falsch, wenn der Konstruktor mit den zwei double-Parametern einfach den Super-Konstruktor mit zwei double-Parametern aufrufen würde, weil sei einfach etwas ganz anderes bedeuten. Das würde leicht zu Fehlern führen, die schwer zu entdecken wären. Oder angenommen, du hast eine funktionierende automatische Konstruktor-Verkettung, und irgendjemand ändert die Superklasse und löscht dem Konstruktor, auf den du dich in der Unterklasse verlässt. Ich denke, an dieser Stelle ist der kleine Mehraufwand durch expliziten Aufruf dem möglichen Chaos durch schwer zu kontrollierende Automatismen vorzuziehen.
 

Zurück
Oben