Wie erzwinge ich, dass die abgeleitete Klasse die Supermethode aufruft? (Wie bei Android)

Lesezeit: 6 Minuten

Benutzer-Avatar
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:

dependencies {
    compile 'com.android.support:support-annotations:22.2.0'
}

http://tools.android.com/tech-docs/support-annotations

@CallSuper

  • 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.

Hier ist die Quelle von Activity#onCreate() – es sind fast alle Kommentare (Original – siehe Zeile ~800):

/**
 * 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:

class Activity
{
  onCreate()
  {
    superCalled = true;
    ...
  }
  ...
}

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!

Benutzer-Avatar
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.

Benutzer-Avatar
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.

1246970cookie-checkWie erzwinge ich, dass die abgeleitete Klasse die Supermethode aufruft? (Wie bei Android)

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy