Wie erzwinge ich, dass die abgeleitete Klasse die Supermethode aufruft? (Wie bei Android)
Lesezeit: 6 Minuten
Peterdk
Ich habe mich gefragt, beim Erstellen von neuen Activity Klassen und überschreibt dann die onCreate() Methode, in Eclipse bekomme ich immer automatisch hinzugefügt: super.onCreate(). Wie kommt es dazu? Gibt es ein Java-Schlüsselwort in der abstrakten oder übergeordneten Klasse, das dies erzwingt?
Ich weiß nicht, ob es illegal ist, die Superklasse nicht aufzurufen, aber ich erinnere mich, dass bei einigen Methoden eine Ausnahme ausgelöst wurde, weil ich dies nicht getan habe. Ist das auch in Java integriert? Kannst du dafür ein Schlüsselwort verwenden? Oder wie wird es gemacht?
Das will ich auch wissen. Und es ist nicht nur Eclipse hilfreich, wenn ich den Aufruf von super.onCreate() entferne, gibt die App einen Laufzeitfehler aus, der besagt: “did not call super.onCreate()”. Also ja, es zwingt Sie wirklich, die Super-Methode aufzurufen. Aber wie?
– Rodrigo Castro
16. Dezember 2011 um 12:39 Uhr
@RodrigoCastro Sie können die Javadocs für jede Methode überprüfen. Zum Beispiel onCreate().
– Benutzer942821
9. Mai 2012 um 4:37 Uhr
Dies wird in der Support-Anmerkungsbibliothek hinzugefügt:
Ja, hier hast du den Nagel auf den Kopf getroffen. Vielen Dank.
– SMBiggs
9. August 2015 um 12:04 Uhr
Noch nicht ausprobiert, aber die Dokumentation lesen. Das wird großartig, denke ich. Dies sollte die akzeptierte Antwort sein.
– Rizwan Sohaib
12. August 2015 um 7:49 Uhr
Alle anderen Antworten sind totaler Mist, außer dieser. Sollte akzeptiert werden.
– Le_Enot
20. Februar 2016 um 8:21 Uhr
@RizwanSohaib es wird dich zu nichts zwingen. Es wird hervorgehoben und Sie wissen lassen, dass Sie es anrufen müssen. Um etwas Komplexeres zu tun, benötigen Sie entweder einen Anmerkungsprozessor oder müssen die Logik selbst implementieren. Je nach IDE sollte es Sie auch am Erstellen hindern.
– frostigwunderbar
28. Februar 2016 um 13:00 Uhr
Perfekte Antwort. Danke vielmals
– Võ Quang Hòa
21. Oktober 2016 um 15:41 Uhr
Wenn Sie wollen Macht Unterklassen, um die Logik der übergeordneten Klasse auszuführen, ist ein allgemeines Muster etwa das folgende:
public abstract class SuperClass implements SomeInterface
{
// This is the implementation of the interface method
// Note it's final so it can't be overridden
public final Object onCreate()
{
// Hence any logic right here always gets run
// INSERT LOGIC
return doOnCreate();
// If you wanted you could instead create a reference to the
// object returned from the subclass, and then do some
// post-processing logic here
}
protected abstract Object doOnCreate();
}
public class Concrete extends SuperClass
{
@Override
protected Object doOnCreate()
{
// Here's where the concrete class gets to actually do
// its onCreate() logic, but it can't stop the parent
// class' bit from running first
return "Hi";
}
}
Dies beantwortet nicht wirklich Ihre Frage, was Eclipse dazu veranlasst, automatisch einen Oberklassenaufruf in die Implementierung einzufügen. aber dann denke ich nicht, dass das sowieso der richtige Weg ist, da dies immer gelöscht werden kann.
Sie können nicht wirklich erzwingen, dass eine Methode die Version der Superklasse mit einem Java-Schlüsselwort oder so etwas aufrufen muss. Ich vermute, dass Ihre Ausnahmen einfach von einem Code in der übergeordneten Klasse stammen, der erwartete Invarianten überprüft, oder etwas, das durch Ihren Ansatz ungültig gemacht wurde. Beachten Sie, dass sich dies leicht vom Auslösen einer Ausnahme unterscheidet Weil du hast es versäumt anzurufen super.onCreate().
Wenn Sie ganz sicher gehen wollen, dass die Superklassen-Methode auch aufgerufen wird, müssen Sie ein wenig tricksen: Lassen Sie die Superklassen-Methode nicht überschreiben, sondern rufen Sie eine überschreibbare geschützte Methode auf.
class Super
{
public final void foo() {
foo_stuff();
impl_stuff();
}
protected void impl_stuff() {
some_stuff_that_you_can_override();
}
}
class Base extends Super
{
protected void impl_stuff() {
my_own_idea_of_impl();
}
}
Auf diese Weise muss der Benutzer Super.foo() oder Base.foo() aufrufen und es wird immer die Basisklassenversion sein, da sie als endgültig deklariert wurde. Das implementierungsspezifische Zeug befindet sich in impl_stuff(), das überschrieben werden kann.
/**
* Called when the activity is starting. This is where most initialization
* should go: calling {@link #setContentView(int)} to inflate the
* activity's UI, using {@link #findViewById} to programmatically interact
* with widgets in the UI, calling
* {@link #managedQuery(android.net.Uri , String[], String, String[], String)} to retrieve
* cursors for data being displayed, etc.
*
* <p>You can call {@link #finish} from within this function, in
* which case onDestroy() will be immediately called without any of the rest
* of the activity lifecycle ({@link #onStart}, {@link #onResume},
* {@link #onPause}, etc) executing.
*
* <p><em>Derived classes must call through to the super class's
* implementation of this method. If they do not, an exception will be
* thrown.</em></p>
*
* @param savedInstanceState If the activity is being re-initialized after
* previously being shut down then this Bundle contains the data it most
* recently supplied in {@link #onSaveInstanceState}. <b><i>Note: Otherwise it is null.</i></b>
*
* @see #onStart
* @see #onSaveInstanceState
* @see #onRestoreInstanceState
* @see #onPostCreate
*/
protected void onCreate(Bundle savedInstanceState) {
mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(
com.android.internal.R.styleable.Window_windowNoDisplay, false);
mCalled = true;
}
Meine Vermutung wäre also, dass das ADT Eclipse-Plugin diesen Aufruf automatisch hinzufügt super.onCreate() für dich. Es ist jedoch eine reine Vermutung.
Um Ihre eigentliche Frage zu beantworten: Die automatische Erstellung des Aufrufs von super.onCreate() ist eine Funktion des ADT-Plugins. In Java können Sie eine Unterklasse nicht direkt zwingen, die Superimplementierung einer Methode aufzurufen, afaik (siehe das in anderen Antworten beschriebene Muster zur Problemumgehung). Beachten Sie jedoch, dass Sie in Android Activity-Objekte (oder Service-Objekte) nicht direkt instanziieren – Sie übergeben eine Absicht an das System und das System instanziiert das Objekt und ruft onCreate() darauf auf (zusammen mit anderen Lebenszyklusmethoden). Das System hat also einen direkten Objektverweis auf die Aktivitätsinstanz und kann (vermutlich) einige boolesche Werte überprüfen, die in der Oberklassenimplementierung von onCreate() auf wahr gesetzt sind. Obwohl ich nicht genau weiß, wie es implementiert ist, sieht es wahrscheinlich so aus:
Und in der “system”-Level-Klasse, die den Intent empfängt und daraus das Activity-Objekt instanziiert:
...
SomeActivitySubclass someActivitySubclassObject = new SomeActivitySubclass();
someActivitySubclassObject.onCreate();
if (!someActivityObject.isSuperCalled())
{
Exception e = new Exception(...) //create an exception with appropriate details
throw e;
}
Meine Vermutung ist, dass es wahrscheinlich etwas komplexer ist, aber Sie bekommen die Idee. Eclipse erstellt den Aufruf automatisch, weil das ADT-Plug-in es der Einfachheit halber anweist. Viel Spaß beim Codieren!
DJ Clayworth
Es gibt nichts in Java, das den Aufruf von super erzwingt, und es gibt viele Beispiele, bei denen Sie das nicht möchten. Der einzige Ort, an dem Sie den Aufruf von super erzwingen können, sind Konstruktoren. Alle Konstruktoren müssen einen Oberklassenkonstruktor aufrufen. Einer (der Konstruktor ohne Argumente) wird eingefügt, wenn Sie keinen explizit schreiben, und wenn es keinen Konstruktor ohne Argumente gibt, müssen Sie ihn explizit aufrufen.
hvgotcodes
Eclipse ist nur hilfreich und erinnert Sie daran, dass Sie die Implementierung der Superklasse aufrufen können, wenn Sie möchten.
Sie erhalten wahrscheinlich einen Fehler, weil Sie etwas Notwendiges nicht tun, was die Superklasse tut, da Sie ihre Implementierung nicht aufrufen.
12469700cookie-checkWie erzwinge ich, dass die abgeleitete Klasse die Supermethode aufruft? (Wie bei Android)yes
Das will ich auch wissen. Und es ist nicht nur Eclipse hilfreich, wenn ich den Aufruf von super.onCreate() entferne, gibt die App einen Laufzeitfehler aus, der besagt: “did not call super.onCreate()”. Also ja, es zwingt Sie wirklich, die Super-Methode aufzurufen. Aber wie?
– Rodrigo Castro
16. Dezember 2011 um 12:39 Uhr
@RodrigoCastro Sie können die Javadocs für jede Methode überprüfen. Zum Beispiel onCreate().
– Benutzer942821
9. Mai 2012 um 4:37 Uhr