public class SuperClass
{
public void method1()
{
System.out.println("superclass method1");
this.method2();
}
public void method2()
{
System.out.println("superclass method2");
}
}
public class SubClass extends SuperClass
{
@Override
public void method1()
{
System.out.println("subclass method1");
super.method1();
}
@Override
public void method2()
{
System.out.println("subclass method2");
}
}
public class Demo
{
public static void main(String[] args)
{
SubClass mSubClass = new SubClass();
mSubClass.method1();
}
}
meine erwartete Ausgabe:
Unterklasse Methode1
Oberklasse Methode1
Oberklasse Methode2
tatsächliche Ausgabe:
Unterklassenmethode1
Oberklassenmethode1
Unterklassenmethode2
Ich weiß, dass ich technisch gesehen eine öffentliche Methode überschrieben habe, aber ich dachte mir, dass, weil ich den Super anrief, alle Anrufe innerhalb des Super im Super bleiben würden, dies nicht geschieht. Irgendwelche Ideen, wie ich es schaffen kann?
java
inheritance
overriding
super
jsonfry
quelle
quelle
Antworten:
Das Schlüsselwort
super
"klebt" nicht. Jeder Methodenaufruf wird einzeln behandelt. Selbst wenn SieSuperClass.method1()
ihn aufrufensuper
müssen, hat dies keinen Einfluss auf andere Methodenaufrufe, die Sie möglicherweise in Zukunft ausführen werden.Das heißt , es gibt keinen direkten Weg rufen
SuperClass.method2()
aus ,SuperClass.method1()
ohne allerdings zu gehen ,SubClass.method2()
wenn Sie mit einer tatsächlichen Instanz arbeitenSuperClass
.Mit Reflection können Sie nicht einmal den gewünschten Effekt erzielen (siehe Dokumentation von
java.lang.reflect.Method.invoke(Object, Object...)
).[EDIT] Es scheint immer noch einige Verwirrung zu geben. Lassen Sie mich eine andere Erklärung versuchen.
Wenn Sie aufrufen
foo()
, rufen Sie tatsächlich aufthis.foo()
. Mit Java können Sie einfach das weglassenthis
. Im Beispiel in der Frage, die Art derthis
istSubClass
.Wenn Java den Code ausführt
SuperClass.method1()
, kommt er schließlich anthis.method2();
Die Verwendung
super
ändert nicht die Instanz, auf die von verwiesen wirdthis
. Der Anruf geht also an,SubClass.method2()
da erthis
vom Typ istSubClass
.Vielleicht ist es einfacher zu verstehen, wenn Sie sich vorstellen, dass Java
this
als versteckter erster Parameter übergeben wird:Wenn Sie dem Aufrufstapel folgen, können Sie sehen, dass sich
this
nichts ändert. Es ist immer die Instanz, in der erstellt wurdemain()
.quelle
super
. Jedes Mal, wenn eine Methode aufgerufen wird, wird der Instanztyp überprüft und mit diesem Typ nach der Methode gesucht, unabhängig davon, wie oft Sie aufgerufen habensuper
. Wenn Sie alsomethod2
eine Instanz von aufrufenSubClass
, wird immer die Instanz vonSubClass
zuerst angezeigt.super
ändert nichts an der Instanz. Es wird kein verstecktes Feld gesetzt, "von nun an sollten alle Methodenaufrufe verwendet werdenSuperClass
". Oderthis
anders ausgedrückt: Der Wert von ändert sich nicht.Sie können nur in den überschreibenden Methoden (oder in anderen Methoden der überschreibenden Klasse) auf überschriebene Methoden zugreifen.
Also: entweder nicht überschreiben
method2()
odersuper.method2()
innerhalb der überschriebenen Version aufrufen .quelle
Sie verwenden das
this
Schlüsselwort, das sich tatsächlich auf die "aktuell ausgeführte Instanz des von Ihnen verwendeten Objekts" bezieht,this.method2();
dh Sie rufen in Ihrer Oberklasse auf, dh es ruft die Methode2 () für das Objekt auf, das Sie verwenden. wieder verwenden, das ist die Unterklasse.quelle
this
wird auch nicht helfen. Ein unqualifizierter Aufruf verwendet implizitthis
method2()
der Compiler sehenthis.method2()
. Selbst wenn Sie das entfernen,this
funktioniert es immer noch nicht. Was @ Sean Patrick Floyd sagt, ist richtigthis
this
sich auf die "konkrete laufende Instanzklasse" (in der Laufzeit bekannt) und nicht (wie das Poster zu glauben scheint) auf die "aktuelle Compilation-Unit-Klasse" (in der das Schlüsselwort verwendet wird, bekannt in) bezieht Kompilierungszeit). Es kann aber auch irreführend sein (wie Shervin betont):this
wird auch implizit mit dem einfachen Methodenaufruf referenziert;method2();
ist das gleiche wiethis.method2();
Ich denke so
Lassen Sie mich diese Unterklasse ein wenig nach links verschieben, um zu zeigen, was sich darunter befindet ... (Mann, ich liebe ASCII-Grafiken)
Mit anderen Worten, zitiert aus der Java-Sprachspezifikation :
Für Laien
this
ist es im Grunde ein Objekt (* das ** Objekt; dasselbe Objekt, das Sie in Variablen verschieben können), die Instanz der instanziierten Klasse, eine einfache Variable in der Datendomäne;super
ist wie ein Zeiger auf einen geliehenen Codeblock, den Sie ausführen möchten, eher wie ein bloßer Funktionsaufruf, und er ist relativ zu der Klasse, in der er aufgerufen wird.Wenn Sie also
super
aus der Oberklasse verwenden, erhalten Sie Code von der Superduper-Klasse [dem Großelternteil], der ausgeführt wird. Wenn Siethis
eine Oberklasse verwenden (oder implizit verwenden), zeigt sie weiterhin auf die Unterklasse (weil niemand sie geändert hat - und niemand könnten).quelle
Wenn Sie nicht möchten, dass superClass.method1 subClass.method2 aufruft, machen Sie method2 privat, damit es nicht überschrieben werden kann.
Hier ist ein Vorschlag:
Wenn es nicht so funktionieren würde, wäre Polymorphismus unmöglich (oder zumindest nicht halb so nützlich).
quelle
Da die einzige Möglichkeit , ein Verfahren zu vermeiden , überschriebenen zu bekommen , ist das Schlüsselwort verwenden Super , habe ich gedacht , um die method2 () aus nach oben Oberklasse zu einer anderen neuen Basisklasse und es dann aus rufen Oberklasse :
Ausgabe:
quelle
this
bezieht sich immer auf das aktuell ausgeführte Objekt.Um den Punkt hier weiter zu veranschaulichen, ist eine einfache Skizze:
Wenn Sie eine Instanz der äußeren Box haben, ein
Subclass
Objekt, wo immer Sie sich in die Box wagen, sogar in denSuperclass
'Bereich', ist es immer noch die Instanz der äußeren Box.Darüber hinaus gibt es in diesem Programm nur ein Objekt, das aus den drei Klassen erstellt wird. Es
this
kann sich also immer nur auf eine Sache beziehen, und zwar:wie im Netbeans 'Heap Walker' gezeigt.
quelle
Berufung
Ausgänge
quelle
Ich glaube nicht, dass Sie es direkt tun können. Eine Problemumgehung wäre, eine private interne Implementierung von Methode2 in der Oberklasse zu haben und diese aufzurufen. Beispielsweise:
quelle
Das Schlüsselwort "this" bezieht sich auf die aktuelle Klassenreferenz. Das heißt, wenn es innerhalb der Methode verwendet wird, ist die 'aktuelle' Klasse immer noch Unterklasse, und daher wird die Antwort erklärt.
quelle
Zusammenfassend zeigt dies auf das aktuelle Objekt und der Methodenaufruf in Java ist von Natur aus polymorph. Die Auswahl der Methode für die Ausführung hängt also vollständig von dem Objekt ab, auf das dies zeigt. Daher ruft das Aufrufen der Methode method2 () von der übergeordneten Klasse die Methode2 () der untergeordneten Klasse auf, da dies auf das Objekt der untergeordneten Klasse verweist. Die Definition ändert sich nicht, unabhängig von der verwendeten Klasse.
PS. Im Gegensatz zu Methoden sind Mitgliedsvariablen der Klasse nicht polymorph.
quelle
Während meiner Recherche nach einem ähnlichen Fall habe ich die Stapelverfolgung in der Unterklassenmethode überprüft, um herauszufinden, woher der Aufruf kommt. Es gibt wahrscheinlich intelligentere Möglichkeiten, dies zu tun, aber es funktioniert für mich und ist ein dynamischer Ansatz.
Ich denke, die Frage nach einer Lösung für den Fall ist vernünftig. Es gibt natürlich Möglichkeiten, das Problem mit verschiedenen Methodennamen oder sogar verschiedenen Parametertypen zu lösen, wie bereits im Thread erwähnt, aber in meinem Fall möchte ich nicht durch verschiedene Methodennamen verwechseln.
quelle
Wenn die Ausgabe der aufgeworfenen Frage weiter erweitert wird, erhalten Sie mehr Einblick in den Zugriffsspezifizierer und das Überschreibungsverhalten.
quelle