Ich las diese Frage und dachte, das wäre leicht zu lösen (nicht, dass es ohne nicht lösbar wäre), wenn man schreiben könnte:
@Override
public String toString() {
return super.super.toString();
}
Ich bin mir nicht sicher, ob es in vielen Fällen nützlich ist, aber ich frage mich, warum es nicht nützlich ist und ob so etwas in anderen Sprachen existiert.
Was denkt ihr?
EDIT: Zur Verdeutlichung: Ja, ich weiß, das ist in Java unmöglich und ich vermisse es nicht wirklich. Dies ist nichts, was ich erwartet hatte und war überrascht, einen Compilerfehler zu bekommen. Ich hatte gerade die Idee und diskutiere sie gerne.
java
superclass
Tim Büthe
quelle
quelle
super.super.toString()
Wenn Sie anrufen möchten, widerspricht dies Ihrer eigenen Entscheidung, wenn Sie eine Klasse erweitern und so alle (nicht einige) ihrer Funktionen akzeptieren .Antworten:
Es verletzt die Kapselung. Sie sollten das Verhalten der übergeordneten Klasse nicht umgehen können. Es ist sinnvoll, manchmal das Verhalten Ihrer eigenen Klasse zu umgehen (insbesondere innerhalb derselben Methode), nicht jedoch das Ihrer Eltern. Angenommen, wir haben eine Basis "Sammlung von Gegenständen", eine Unterklasse, die "eine Sammlung roter Gegenstände" darstellt, und eine Unterklasse derjenigen, die "eine Sammlung großer roter Gegenstände" darstellt. Es ist sinnvoll zu haben:
Das ist in Ordnung - RedItems kann immer sicher sein, dass alle darin enthaltenen Elemente rot sind. Nehmen wir nun an wir waren fähig super.super.add () aufzurufen:
Jetzt können wir hinzufügen, was wir wollen, und die Invariante
RedItems
ist gebrochen.Ist das sinnvoll?
quelle
Ich denke, Jon Skeet hat die richtige Antwort. Ich möchte nur hinzufügen, dass Sie durch Casting auf schattierte Variablen aus Superklassen von Superklassen zugreifen können
this
:welches die Ausgabe erzeugt:
(Beispiel aus dem JLS )
Dies funktioniert jedoch nicht für Methodenaufrufe, da Methodenaufrufe basierend auf dem Laufzeittyp des Objekts bestimmt werden.
quelle
Ich denke, der folgende Code erlaubt in den meisten Fällen die Verwendung von super.super ... super.method (). (auch wenn es hässlich ist, das zu tun)
Zusamenfassend
Verwendungszweck :
quelle
super.super.
Programmierer dazu einlädt, neue, verschlungene und ungeheure Wege zu finden, um sich bei der Suche nach einer Problemumgehung in den Fuß zu schießen. Dies ist ein perfektes Beispiel dafür, weil Ihre Kollegen Sie wahrscheinlich so sehr dafür hassen werden, etwas zu schreiben so, dass sie dich persönlich und buchstäblich in den Fuß schießen. +1Ich habe nicht genug Ruf, um Kommentare abzugeben, daher werde ich dies zu den anderen Antworten hinzufügen.
Jon Skeet antwortet ausgezeichnet mit einem schönen Beispiel. Matt B hat einen Punkt: Nicht alle Superklassen haben Supers. Ihr Code würde kaputt gehen, wenn Sie ein Super eines Super nennen würden, das kein Super hat.
Bei der objektorientierten Programmierung (was Java ist) dreht sich alles um Objekte, nicht um Funktionen. Wenn Sie eine aufgabenorientierte Programmierung wünschen, wählen Sie C ++ oder etwas anderes. Wenn Ihr Objekt nicht in die Superklasse passt, müssen Sie es der "Großelternklasse" hinzufügen, eine neue Klasse erstellen oder eine andere Superklasse finden, in die es passt.
Persönlich habe ich festgestellt, dass diese Einschränkung eine der größten Stärken von Java ist. Code ist im Vergleich zu anderen Sprachen, die ich verwendet habe, etwas starr, aber ich weiß immer, was mich erwartet. Dies hilft beim "einfachen und vertrauten" Ziel von Java. In meinen Augen ist es nicht einfach oder vertraut, super.super anzurufen. Vielleicht ging es den Entwicklern genauso?
quelle
Dafür gibt es einige gute Gründe. Möglicherweise haben Sie eine Unterklasse mit einer Methode, die falsch implementiert ist, aber die übergeordnete Methode ist korrekt implementiert. Da es zu einer Bibliothek eines Drittanbieters gehört, können / möchten Sie die Quelle möglicherweise nicht ändern. In diesem Fall möchten Sie eine Unterklasse erstellen, aber eine Methode überschreiben, um die super.super-Methode aufzurufen.
Wie einige andere Poster zeigen, ist es möglich, dies durch Reflexion zu tun, aber es sollte möglich sein, so etwas zu tun
(SuperSuperClass this) .theMethod ();
Ich beschäftige mich gerade mit diesem Problem - die schnelle Lösung besteht darin, die Superklassenmethode zu kopieren und in die Unterklassenmethode einzufügen :)
quelle
Zusätzlich zu den sehr guten Punkten, die andere gemacht haben, gibt es meines Erachtens noch einen weiteren Grund: Was ist, wenn die Oberklasse keine Oberklasse hat?
Da sich jede Klasse natürlich (zumindest) erweitert
Object
,super.whatever()
wird immer auf eine Methode in der Oberklasse verwiesen. Aber was ist, wenn sich Ihre Klasse nur erweitertObject
- worauf würdesuper.super
sich das dann beziehen? Wie soll mit diesem Verhalten umgegangen werden - ein Compilerfehler, ein NullPointer usw.?Ich denke, der Hauptgrund, warum dies nicht erlaubt ist, ist, dass es die Kapselung verletzt, aber dies könnte auch ein kleiner Grund sein.
quelle
Ich denke, wenn Sie eine Methode überschreiben und die gesamte Super-Class-Version davon (wie zum Beispiel für
equals
) verwenden möchten, möchten Sie praktisch immer zuerst die direkte Superclass-Version aufrufen, die wiederum die Superclass-Version aufruft, wenn dies gewünscht wird .Ich denke, es macht nur selten Sinn (wenn überhaupt. Ich kann mir keinen Fall vorstellen, in dem dies der Fall ist), eine beliebige Superklassenversion einer Methode aufzurufen. Ich weiß nicht, ob das in Java überhaupt möglich ist. Dies kann in C ++ erfolgen:
quelle
Vermutlich, weil es nicht so oft verwendet wird. Der einzige Grund, warum ich es sehen konnte, ist, wenn Ihr direkter Elternteil einige Funktionen überschrieben hat und Sie versuchen, sie wieder auf das Original zurückzusetzen.
Das scheint mir gegen die OO-Prinzipien zu verstoßen, da der direkte Elternteil der Klasse enger mit Ihrer Klasse verwandt sein sollte als der Großelternteil.
quelle
Schauen Sie sich dieses Github-Projekt an, insbesondere die Variable objectHandle. Dieses Projekt zeigt, wie man die Großelternmethode eines Enkels tatsächlich und genau aufruft.
Für den Fall, dass der Link unterbrochen wird, ist hier der Code:
Viel Spaß beim Codieren !!!!
quelle
Wenn möglich, würde ich den Körper der super.super-Methode in eine andere Methode einfügen
Oder wenn Sie die Super-Super-Klasse nicht ändern können, können Sie Folgendes versuchen:
In beiden Fällen ist die
Ergebnisse zu "Ich bin super super"
quelle
Es scheint möglich zu sein, zumindest die Klasse der Oberklasse der Oberklasse, wenn auch nicht unbedingt die Instanz davon, durch Reflexion zu erhalten; Wenn dies nützlich sein könnte, beachten Sie bitte das Javadoc unter http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html#getSuperclass ()
quelle
run: A BUILD SUCCESSFUL (Gesamtzeit: 0 Sekunden)
quelle
Das Aufrufen von super.super.method () ist sinnvoll, wenn Sie den Code der Basisklasse nicht ändern können. Dies passiert häufig, wenn Sie eine vorhandene Bibliothek erweitern.
Fragen Sie sich zuerst, warum Sie diese Klasse erweitern? Wenn die Antwort "weil ich sie nicht ändern kann" lautet, können Sie ein genaues Paket und eine Klasse in Ihrer Anwendung erstellen und eine ungezogene Methode neu schreiben oder einen Delegaten erstellen:
Beispielsweise können Sie org.springframework.test.context.junit4.SpringJUnit4ClassRunner erstellen in Ihrer Anwendung die Klasse sodass diese Klasse vor der realen Klasse aus jar geladen werden sollte. Schreiben Sie dann Methoden oder Konstruktoren neu.
Achtung: Dies ist ein absoluter Hack, und es wird dringend empfohlen, ihn zu verwenden, aber er funktioniert! Die Verwendung dieses Ansatzes ist aufgrund möglicher Probleme mit Klassenladern gefährlich. Dies kann auch jedes Mal zu Problemen führen, wenn Sie eine Bibliothek aktualisieren, die überschriebene Klassen enthält.
quelle
Ich hatte Situationen wie diese, in denen die Architektur gemeinsame Funktionen in einer gemeinsamen CustomBaseClass erstellen soll, die im Auftrag mehrerer abgeleiteter Klassen implementiert wird. Wir müssen jedoch die gemeinsame Logik für eine bestimmte Methode für eine bestimmte abgeleitete Klasse umgehen. In solchen Fällen müssen wir eine super.super.methodX-Implementierung verwenden.
Dies erreichen wir durch die Einführung eines booleschen Elements in der CustomBaseClass, mit dem die benutzerdefinierte Implementierung selektiv verschoben und bei Bedarf der Standard-Framework-Implementierung nachgegeben werden kann.
Mit guten Architekturprinzipien, die sowohl im Framework als auch in der App befolgt werden, könnten wir solche Situationen jedoch leicht vermeiden, indem wir den hasA-Ansatz anstelle des isA-Ansatzes verwenden. Es ist jedoch nicht immer sehr praktisch, eine gut gestaltete Architektur zu erwarten, und daher die Notwendigkeit, sich von soliden Designprinzipien zu lösen und solche Hacks einzuführen. Nur meine 2 Cent ...
quelle
@ Jon Skeet Schöne Erklärung. IMO, wenn jemand die Methode super.super aufrufen möchte, muss man das Verhalten des unmittelbaren Elternteils ignorieren wollen, aber auf das Verhalten des Großelternteils zugreifen wollen. Dies kann durch Instanz von erreicht werden. Wie unten Code
Hier ist Fahrerklasse,
Ausgabe davon wird sein
Das Druckklassenverhalten der Klasse B wird in diesem Fall ignoriert. Ich bin mir nicht sicher, ob dies eine ideale oder gute Praxis ist, um super.super zu erreichen, aber es funktioniert immer noch.
quelle
Wenn Sie glauben, dass Sie die Oberklasse benötigen, können Sie sie in einer Variablen für diese Klasse referenzieren. Zum Beispiel:
Sollte ausdrucken:
quelle
new UltraFoo.getNumber()
nicht kompilieren, da du dort Klammern verpasst hast. Ich habe jedoch gerade meine Donvote entfernt, da das Konzept Ihres Codes jetzt ziemlich klar ist, danke!IMO, es ist ein sauberer Weg, um
super.super.sayYourName()
Verhalten in Java zu erreichen .Ausgabe:
Request to lie: d.sayYourName(true) returns Grandma Fedora
Request not to lie: d.sayYourName(false) returns Little girl Masha
quelle
Ich denke, dies ist ein Problem, das die Erbschaftsvereinbarung bricht.
Indem Sie eine Klasse erweitern, gehorchen Sie deren Verhalten und Funktionen.
Während Sie anrufen
super.super.method()
, möchten Sie Ihre eigene Gehorsamvereinbarung brechen.Sie können einfach nicht aus der Superklasse auswählen .
Es kann jedoch vorkommen, dass Sie anrufen müssen
super.super.method()
- normalerweise ein schlechtes Designzeichen, in Ihrem Code oder in dem Code, den Sie erben!Wenn die Super- und Super-Super- Klassen nicht überarbeitet werden können (etwas Legacy-Code), entscheiden Sie sich für Komposition statt Vererbung.
Das Aufbrechen der Kapselung erfolgt, wenn Sie einige Methoden überschreiben , indem Sie den gekapselten Code aufheben . Die Methoden, die nicht überschrieben werden sollen, sind als endgültig markiert .
quelle
In C # können Sie eine Methode eines beliebigen Vorfahren wie folgt aufrufen:
Dies können Sie auch in Delphi tun:
In Java können Sie einen solchen Fokus jedoch nur mit bestimmten Geräten erzielen. Ein möglicher Weg ist:
Ergebnisausgabe von objC.DoIt ():
quelle
Es ist einfach einfach zu machen. Zum Beispiel:
C-Unterklasse von B und B-Unterklasse von A. Beide drei haben beispielsweise die Methode methodName ().
Laufklasse C Die Ausgabe lautet: Klasse A Klasse C.
Anstelle von Ausgabe: Klasse A Klasse B Klasse C.
quelle
Ausgabe: Gedruckt im GrandDad
quelle
super.super.method()
in Java kein gültiger Code vorhanden ist.Das Schlüsselwort super ist nur eine Möglichkeit, die Methode in der Oberklasse aufzurufen. Im Java-Tutorial: https://docs.oracle.com/javase/tutorial/java/IandI/super.html
Wenn Ihre Methode eine der Methoden ihrer Oberklasse überschreibt, können Sie die überschriebene Methode mithilfe des Schlüsselworts super aufrufen.
Glaube nicht, dass es eine Referenz des Superobjekts ist !!! Nein, es ist nur ein Schlüsselwort, um Methoden in der Oberklasse aufzurufen.
Hier ist ein Beispiel:
Wenn Sie aufrufen
cat.doSth()
, wird die MethodedoSth()
in der KlasseAnimal
gedrucktthis
und es handelt sich um eine Katze.quelle