super vs. this

blz

Bekanntes Mitglied
Hallo, ich habe jetzt lange über super und this gelesen und denke eigentlich schon, die Konzepte verstanden zu haben. Trotzdem bleibt folgende Frage ...:

Ich befinde mich in einer erbenden Klasse, z. B. MyFrame, und möchte im Konstruktor eine Methode, z. B. setSize(50, 50) aufrufen.

Nun möchte ich möglichst sauberes Java programmieren und weiß, dass ich eine Methode immer für ein Objekt aufrufe.
Also wäre es doch konsequent, this.setSize(50, 50) zu schreiben, weil mir this die Referenz auf das Objekt, in dem ich mich befinde, liefert; für dieses möchte ich die Größe ändern.
Genauso könnte ich aber auch sagen, die Methode setSize(…) steht in der Oberklasse, ich möchte ganz explizit programmieren und daher super.setSize() schreiben und damit angeben, dass die Methode der Oberklasse gewählt werden soll. Für welches Objekt aber?
Wäre nicht ein this.super.setSize(…) logisch??
 
this zeigt dabei jeweils auf die Definition in der aktuellen Klasse, super auf die Definitionen der Super-Klasse.

Der Unterschied ist dann relevant, wenn du eine Methode überschrieben hast.
mit super würde die ursprüngliche Methode Aufgerufen werden, mit this die in der aktuellen Klasse.

So gut wie immer ist this das passende, außer, man möchte in der überschreibenden Methode noch die ursprüngliche aufrufen oder im Konstruktor den Konstruktor der Oberklasse ausführen.


Wenn du z.B. setSize so überschrieben hast, das jedes Mal noch die neue Größe ausgegeben wird:
Java:
@Override
public void setSize(int w, int h) {
  super.setSize(w,h);//Die ursprüngliche Methode aufrufen, damit die Größe auch verändert wird
  System.out.print("neue Größe: "+w+", "+h);//deine eigenen Ergänzungen ausführen
}


BTW: JFrame extenden ist selten sinnvoll, besser ist es, einfach eine Instanzvariable vom Typ JFrame zu nutzen 😉
 
Zuletzt bearbeitet:
So meine ich es nicht.
Schon klar, dass ich es im Alltag nicht so schreibe.
Ich verstehe aber dennoch nicht ganz, wo mein Denkfehler im letzten Absatz liegt.
 
Zu deinem letztem Absatz: du möchtest setSize aufrufen, wie es für deine aktuelles Objekt definiert ist -> also this.
Brauchst du zwingen die Definition der Oberklasse? Nein. Also auch kein super.
super wäre in dem Kontext beim Lesen eher hinderlich - das führt zu dem Eindruck, dass die Methode überschrieben wird, du aber explizit die überschriebene Variante meiden möchtest.
 
ok, dann nehmen wir doch an, ich hätte setSize in der Unterklasse überschrieben
wäre dann this.super.setSize nicht vom Prinzip her richtig gedacht? (wenn ich die Methode der Oberklasse für ein Objekt der Unterklasse aufrufen will)
 
Zuletzt bearbeitet:
this.super gibts nicht 😉

mit super vermeidest du explizit die überschriebene Variante. Wenn du das möchtest, ist super das richtige. Allerdings ist das in den seltensten Fällen nötig - oder warum überschreibst du die Methode, wenn du sie dann gar nicht nutzen möchtest? 😉
 
Ja, das ich die Variante explizit vermeide, ist mir klar.
Dass das hier relativ sinnlos erscheint, auch - ich habe mich nicht bemüht, das Bsp. sinnvoll zu konstruieren.
Dennoch könnte es sicherlich einen Anwendungsfall geben, bei dem man die Methode aufrufen will.
Was ich einfach hören möchte ist, dass ich eigentlich richtig denke und die Prinzipien eigentlich richtig anwenden möchte und dass es eigentlich der Fehler von Java ist, dass es kein this.super gibt 🙂
 
Was soll denn dann this.super sein? Also sowohl vom Typ als auch vom tatsächlichen Wert her? "this" ist doch das Objekt, auf dem die Methode aufgerufen wird. Das Objekt hat nur einen einzigen Laufzeittyp, nämlich jene Klasse, über deren Konstruktor das Objekt erzeugt wurde.
this.super macht überhaupt gar keinen Sinn. Es müsste ja sowieso auch wieder dasselbe Objekt wie "this" zurückliefern.
EDIT: Letzten Absatz entfernt. War falsch. 🙂
 
Zuletzt bearbeitet:
dass es eigentlich der Fehler von Java ist, dass es kein this.super gibt
Nö, es gibt this und es gibt super - was soll man da noch mit this.super?

Das was du (vermutlich) meinst entspricht einfach super.

Dass das hier relativ sinnlos erscheint, auch - ich habe mich nicht bemüht, das Bsp. sinnvoll zu konstruieren.
Für sowas ist ein sinnvolles Beispiel manchmal extrem hilfreich 😉
 
Vielleicht sollte man auch noch erwähnen, dass "super" alleine auch kein gültiger Ausdruck ist, genauso wenig wie "this.super" es wäre; "this" aber schon.
Das Schlüsselwort "super" ist nur in Zusammenhang mit einem folgenden Methodenaufruf wie "super.irgendwas()" bzw. mit eventuellen Argumenten als Superkonstruktoraufruf "super(...)" gültig.
In dem Sinne hast du also schon ein bisschen Recht. "super" ist ein klein wenig ein Hilfsmittel, um bei "super.irgendwas()" eigentlich zu sagen: "Rufe die Methode irgendwas() auf this auf, aber verwende für das Finden der tatsächlichen überschriebenen Methode im Dynamic Dispatch NICHT die aktuelle Klasse, in der der super.irgendwas() Aufruf steht, falls irgendwas() in dieser Klasse überschrieben wurde, sondern verwende höchstens die direkte Oberklasse, falls diese irgendwas() definiert. Ansonsten suche, wie sonst auch, die Vererbungshierarchie hinauf, bis du ein irgendwas() findest."
 
Ja, das ich die Variante explizit vermeide, ist mir klar.
Dass das hier relativ sinnlos erscheint, auch - ich habe mich nicht bemüht, das Bsp. sinnvoll zu konstruieren.
Dennoch könnte es sicherlich einen Anwendungsfall geben, bei dem man die Methode aufrufen will.
Was ich einfach hören möchte ist, dass ich eigentlich richtig denke und die Prinzipien eigentlich richtig anwenden möchte und dass es eigentlich der Fehler von Java ist, dass es kein this.super gibt 🙂
Hier habe ich mich verkürzt ausgedrückt, weil ich mich auf meine vorigen Posts bezogen habe.
Ich meinte damit, "dass es eigentlich der Fehler von Java ist, dass es kein this.super.setSize(...) gibt"
Und ansonsten meinte ich genau das, was httpdigest im Post #13 noch einmal formuliert hat.
 
Hier habe ich mich verkürzt ausgedrückt, weil ich mich auf meine vorigen Posts bezogen habe.
Ich meinte damit, "dass es eigentlich der Fehler von Java ist, dass es kein this.super.setSize(...) gibt"
Und ansonsten meinte ich genau das, was httpdigest im Post #13 noch einmal formuliert hat.
Was soll denn der Unterscheid zwischen this.super.setSize(...) und super.setSize(...) sein?
Das was in #13 steht ist nur die Erklärung dessen, was super macht - und doch kein Beispiel für irgendwas?
 
Nach fast einem Jahr lässt mich das Problem einer sprachlichen/didaktischen sauberen Abgrenzung von this und super immer noch nicht ganz los 🙂
Deswegen starte ich jetzt hier nochmal einen neuen Versuch:

Eine Methode wird in Java immer für ein Objekt aufgerufen.
Üblicherweise schreibt man das wie folgt auf:
Referenzattribut, das auf das Objekt verweist - Punkt - Methodenname, evtl. mit Parameterwerten.

Rufe ich nun innerhalb einer Methode a() einer Klasse eine andere Methode b() derselben Klasse auf, soll diese Methode ja für das Objekt ausgeführt werden, für das a() aufgerufen wurde; also für das "aktuelle Objekt".
Die Referenz auf das aktuelle Objekt bekomme ich via this.

Um also die oben beschriebene Punktnotation für Methodenaufrufe logisch und durchgängig anzuwenden, würde ich nun (innerhalb von a()) this.b() schreiben.

Wenn ich jetzt aber die Methode b() in der aktuellen Klasse überschrieben habe und in diesem Fall die ursprüngliche Methode aus einer Oberklasse aufrufen möchte, muss ich das Schlüsselwort super verwenden, also super.b() aufrufen.

Und hier - finde ich - beginnt die Ausführung nicht mehr 100% ig logisch zu sein, denn:
Ich rufe die Methode ja immer noch für ein Objekt der aktuellen Klasse auf. Also könnte man argumentieren, muss man this. voranstellen. Dann ruft man die Methode nicht aus dieser Klasse, sondern aus der Oberklasse auf. Also schreibt man super. Dann noch den Methodenaufruf. Ergäbe this.super.b();

Vllt. könnte man die Funktion der Schlüsselworte this und super in diesem Fall eher so formulieren:
this ist die Referenz auf das aktuelle Objekt dieser Klasse.
super ist die Referenz auf das aktuelle Objekt dieser Klasse, wenn man es (vorübergehend) als ein Objekt der Oberklasse betrachtet.

Was meint ihr?
 
Ich kann deine Denkweise mit this.super.methode() komplett nachvollziehen 🙂 verstehe was du meinst und von der Notation her klingt es ja auch logisch. Weitergedacht könnte man auch argumentieren, dass this.super.methode() eigentlich unnötig ist, da methode() bei vorangestellen super sich ja ganz klar auf this bezieht - also trotzdem noch dein Ansatz. Da könnte man aber dann theoretisch deinen Weg this.super.methode() dennoch als richtig sehen und ihn gelten lassen.
Hoffe das Problem lässt dich dann mal los 😀
 
In Eurer Denkweise this.super steckt ein kleiner Fehler: super ist weder eine Objektreferenz noch ist die Superklasse eine objektbezogene Eigenschaft.

Es geht einfach um die Angabe des Ausführungskontexts für this - das Objekt selbst ändert sich dabei nicht, d. h. this ist in allen Methoden, die entlang der Kette ausgeführt werden, immer gleich.
 
Das stimmt ja. super soll bei mir auch gar keine Obkektreferenz markieren. In Worte gefasst meinte ich bei this.super auch eher: "der Ausführungskontext der Superklasse des Typs von this". Das ganze gibt es ja sowieso nicht. Es geht nur um die Denkweise und ob es logisch erscheinen würde - was meiner Ansicht Sinn machen würde.
 
"der Ausführungskontext der Superklasse des Typs von this" und genau das ist falsch. Es geht nicht um die Superklasse des Typs von this, sondern um die Superklasse der Klasse, deren Code gerade ausgeführt wird. Würde es sich um die Superklasse des Typs von this handeln, hättest Du ganz schnell eine Endlosrekursion.
 
Wenn du in der Methode der Superklasse (nennen wir sie `B`) aber wieder ein `super.dieselbeMethode()` stehen hättest (um zu sagen: "Rufe auch hier die Methode in der nächsten Superklasse `C` auf"), dann würde das ja bedeuten, dass diese Methode in `B` nochmal aufgerufen werden würde und nicht die Methode in einer weiteren Oberklasse `C`, weil sich der Typ von `this` ja effektiv nicht geändert hat.
Welche konkrete Methode aufgerufen wird, hängt also nicht vom Typ von `this` ab, sondern eben wie bereits gesagt, von der Klasse, in dem der super-Aufruf steht.
 
Ok ja verstehe. Ich hab das this in der Superklasse in diesem Fall als eine Art Instanz der Superklasse interpretiert. Also sozusagen eine "Teilinstanz" des eigentlichen Objekts. Nur dann hätte es nämlich Sinn ergeben.
 

Zurück
Oben