Wann soll die Methode super() beim Überschreiben NICHT aufgerufen werden?
Lesezeit: 7 Minuten
Sandalen
Wenn ich meine eigene benutzerdefinierte Android-Klasse erstelle, kann ich extend seine einheimische Klasse. Wenn ich dann die Basismethode überschreiben möchte, rufe ich immer auf super() Methode, so wie ich es immer mache onCreate, onStopetc.
Und ich dachte, das ist es, denn von Anfang an riet uns das Android-Team, immer anzurufen super bei jeder Methodenüberschreibung.
Aber in viele Bücher Ich sehe, dass Entwickler, die erfahrener sind als ich, es oft unterlassen, anzurufen super und ich bezweifle wirklich, dass sie es aus Mangel an Wissen tun. Schauen Sie sich zum Beispiel dieses Basic an SAXOPHON Parser-Klasse wo super wird weggelassen startElement, characters und endElement:
public class SAXParser extends DefaultHandler{
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if(qName.equalsIgnoreCase("XXY")) {
//do something
}
}
public void characters(char[] ch, int start, int length) throws SAXException {
//do something
}
public void endElement(String uri, String localName, String qName) throws SAXException {
if(qName.equalsIgnoreCase("XXY")) {
//do something
}else () {
//do something
}
}
}
Wenn Sie versuchen, eine Überschreibungsmethode über Eclipse oder eine andere IDE zu erstellen, super werden immer als Teil eines automatisierten Prozesses erstellt.
Dies war nur ein einfaches Beispiel. Bücher sind voll von ähnlichem Code.
Woher wissen sie, wann Sie anrufen müssen? super und wann kann man es weglassen anzurufen?
PS. Binden Sie sich nicht an dieses konkrete Beispiel. Es war nur ein zufällig ausgewähltes Beispiel aus vielen Beispielen.
(Das mag wie eine Anfängerfrage klingen, aber ich bin wirklich verwirrt.)
endElementDas API-Dokument von sagt: „Standardmäßig nichts tun. Anwendungsautoren können diese Methode überschreiben …“, was bedeutet, dass Sie super sicher aufrufen können, weil es „nichts“ tut, aber Sie müssen es nicht und Sie können es wirklich überschreiben. Sie können oft erkennen, ob Sie es tun müssen / können / sollten, wenn Sie das Dokument für diese Methode lesen.
– zapl
20. April 2012 um 11:07 Uhr
Kleines Beispiel: Ich verwende onBackPressed() im Begrüßungsbildschirm, und ich rufe NICHT super an, damit es nicht aus dem Begrüßungsfenster geht, es deaktiviert nur die Schaltfläche.
– Bojan Kogoj
25. April 2012 um 3:10 Uhr
Xavi Lopez
Durch den Aufruf der super Methode, du bist es nicht überschreiben das Verhalten der Methode, du bist verlängern es.
Ein Anruf bei super führt jede Logik aus, die die Klasse, die Sie erweitern, für diese Methode definiert hat. Berücksichtigen Sie, dass es in dem Moment wichtig sein könnte, in dem Sie anrufen super‘s-Implementierung in Ihrer Methode überschreibt. Zum Beispiel:
public class A {
public void save() {
// Perform save logic
}
}
public class B extends A {
private Object b;
@Override
public void save() {
super.save(); // Performs the save logic for A
save(b); // Perform additional save logic
}
}
Ein Anruf bei B.save() wird die durchführen save() Logik für beide A und B, in dieser bestimmten Reihenfolge. Wenn Sie nicht angerufen haben super.save() Innerhalb B.save(), A.save() würde nicht angerufen. Und wenn du angerufen hast super.save() nach save(b), A.save() würde danach effektiv durchgeführt werden B.save().
Wenn Sie wollen überschreibensuper‘s Verhalten (das heißt, ignorieren Sie seine Implementierung vollständig und stellen Sie alles selbst bereit), sollten Sie nicht anrufen super.
In dem SAXParser Beispiel, das Sie angeben, die Implementierungen von DefaultHandler denn diese Methoden sind einfach leer, sodass Unterklassen sie überschreiben und ein Verhalten für diese Methoden bereitstellen können. In dem javadoc für diese Methode wird auch darauf hingewiesen.
public void startElement (String uri, String localName,
String qName, Attributes attributes) throws SAXException {
// no op
}
Über die super() Standardaufruf in Code, der von IDEs generiert wird, wie @barsju wies in seinem Kommentar darauf hin, dass es in jedem Konstruktor einen impliziten Aufruf von gibt super() (auch wenn Sie es nicht in Ihren Code schreiben), was in diesem Zusammenhang einen Aufruf von bedeutet superStandardkonstruktor von . Das IDE schreibt es einfach für Sie auf, aber es würde auch aufgerufen werden, wenn Sie es entfernen würden. Beachten Sie auch, dass beim Implementieren von Konstruktoren super() oder eine seiner Varianten mit Argumenten (dh super(x,y,z)) kann nur angerufen werden ganz am Anfang der Methode.
Beachten Sie dies auch nicht für Konstruktoren super() (der Standardkonstruktor der Superklasse) wird immer aufgerufen, auch wenn Sie ihn nicht angeben. Wenn die Oberklasse keinen Standardkonstruktor hat, erhalten Sie einen Kompilierungsfehler, wenn Sie nicht explizit einen der Konstruktoren der Oberklasse als erste Anweisung im Unterklassenkonstruktor aufrufen.
– Barsju
20. April 2012 um 10:55 Uhr
Ja, es ist im Grunde nur Faulheit – bei Methoden, von denen wir wissen, dass sie nichts bewirken, lassen Sie sie einfach der Kürze halber weg
– Voo
20. April 2012 um 10:59 Uhr
Vielen Dank für Ihre wertvollen Kommentare, @barjsu, ich habe diese Details in die Antwort aufgenommen.
– Xavi Lopez
20. April 2012 um 11:09 Uhr
yorkw
Woher wissen sie, wann Sie Super anrufen müssen und wann Sie es unterlassen können, anzurufen?
Wenn eine spezielle API-Methode eine entscheidende Bedeutung für den Lebenszyklus des zugrunde liegenden Framework-Kontexts hat, wird sie in der API-Dokumentation normalerweise immer explizit angegeben und hervorgehoben, wie z Activity.onCreate() API-Dokumentation. Wenn die API einem robusten Design folgt, sollte sie außerdem einige Ausnahmen auslösen, um den Consumer-Entwickler zur Kompilierzeit des Projekts zu warnen und sicherzustellen, dass sie zur Laufzeit keinen Fehler generiert.
Wenn dies nicht ausdrücklich in der API-Dokumentation angegeben ist, kann der Consumer-Entwickler davon ausgehen, dass die API-Methode nicht zwingend aufgerufen werden muss, wenn sie überschrieben wird. Es liegt am Consumer-Entwickler, zu entscheiden, ob das Standardverhalten verwendet werden soll (rufen Sie die super -Methode) oder vollständig überschreiben.
Wenn die Bedingung zulässig ist (ich liebe Open-Source-Software), kann der Consumer-Entwickler jederzeit den API-Quellcode überprüfen und sehen, wie die Methode tatsächlich unter der Haube geschrieben ist. Kasse Activity.onCreate() Quelle und DefaultHandler.startElement() Quelle zum Beispiel.
Danke, dass du mir weitere Dinge erklärt hast. Danke, dass Sie mich daran erinnern, den Quellcode zu überprüfen.
– Sandalen
21. April 2012 um 15:17 Uhr
Michael
Der Test, den Sie in Ihrem Kopf machen sollten, ist:
“Möchte ich, dass die gesamte Funktionalität dieser Methode für mich erledigt wird, und dann etwas danach tun?” Wenn ja, dann wollen Sie anrufen super(), und beenden Sie dann Ihre Methode. Dies gilt für “wichtige” Methoden wie z onDraw()die viele Dinge im Hintergrund erledigt.
Wenn Sie nur einen Teil der Funktionalität benötigen (wie bei den meisten Methoden, die Sie überschreiben werden), möchten Sie wahrscheinlich nicht aufrufen super().
Brunnen Xavi gab eine bessere Antwort .. aber Sie wissen wahrscheinlich, was es tut super() tun, wenn es in einer überschriebenen Methode aufgerufen wird … es zeigt an, was Sie mit dem Standardverhalten gemacht haben.
z.B:
onDraw()
Methode in der Ansichtsklasse, wenn sie überschrieben wird. Sie zeichnen etwas, bevor Sie super.onDraw () sagen. Es wird angezeigt, sobald die Ansicht vollständig gezeichnet ist super ist notwendig, da Android einige äußerst wichtige Dinge zu tun hat (wie onCreate())
aber zur selben Zeit
onLongClick()
Wenn Sie dies überschreiben, möchten Sie nicht super aufrufen, da es einen Dialog mit einer Liste von Optionen für eine EditText- oder eine andere ähnliche Ansicht aufruft. Das ist der grundlegende Unterschied. Sie haben manchmal die Wahl, es zu verlassen andere Methoden wie onCreate() , onStop() Sie sollten das Betriebssystem damit umgehen lassen.
Ich habe eine Constraint-Array-Liste wie implementiert
public class ConstraintArrayList<T> extends ArrayList<T> {
ConstraintArrayList(Constraint<T> cons) {this.cons = cons;}
@Override
public boolean add(T element) {
if (cons.accept(element))
return super.add(element);
return false;
}
}
Wenn Sie sich den Code ansehen, führt er einfach einige Vorabprüfungen durch, bevor er die Superklasse tatsächlich das eigentliche Hinzufügen von Elementen zur Liste durchführt. Dies gibt einen der zwei Gründe für das Überschreiben von Methoden an:
Erweiterbarkeit, wo Sie erweitern möchten, was die Superklasse kann
Spezifität, wenn Sie durch Polymorphismus ein bestimmtes Verhalten hinzufügen möchten, wie im allgemeinen Tierreich-Beispiel der Bewegungssemantik, wo die Art und Weise, wie sich Vögel bewegen (fliegen) und Frösche bewegen (hüpfen), für jede Unterklasse spezifisch sind.
Peter Mortensen
Ich habe Ihre Frage nicht klar verstanden, aber wenn Sie fragen, warum rufen Sie nicht an? super Methode:
Es gibt einen Grund für den Anruf super Methode: Wenn es in der übergeordneten Klasse keinen Konstruktor mit Nullargumenten gibt, ist es nicht möglich, dafür eine untergeordnete Klasse zu erstellen. Sie müssen also entweder einen Konstruktor ohne Argumente in der übergeordneten Klasse behalten oder definieren super() Calling-Anweisung mit argument(how much argument constructor you have used in super class) an der Spitze des untergeordneten Klassenkonstruktors.
Ich hoffe das hilft. Wenn nicht, lassen Sie es mich wissen.
Dominik
Für diejenigen, die sich auch gefragt haben, welche überschriebenen Methoden von Android Framework aufgerufen werden sollen super und diese Frage gefunden – hier ein aktueller Hinweis aus 2019 – Android Studio 3+ sagt Ihnen, wann Sie es brauchen.
13205700cookie-checkWann soll die Methode super() beim Überschreiben NICHT aufgerufen werden?yes
endElement
Das API-Dokument von sagt: „Standardmäßig nichts tun. Anwendungsautoren können diese Methode überschreiben …“, was bedeutet, dass Sie super sicher aufrufen können, weil es „nichts“ tut, aber Sie müssen es nicht und Sie können es wirklich überschreiben. Sie können oft erkennen, ob Sie es tun müssen / können / sollten, wenn Sie das Dokument für diese Methode lesen.– zapl
20. April 2012 um 11:07 Uhr
Kleines Beispiel: Ich verwende onBackPressed() im Begrüßungsbildschirm, und ich rufe NICHT super an, damit es nicht aus dem Begrüßungsfenster geht, es deaktiviert nur die Schaltfläche.
– Bojan Kogoj
25. April 2012 um 3:10 Uhr