派生クラスにスーパーメソッドを呼び出させる方法は?(Androidのように)


85

新しいActivityクラスを作成してからonCreate()メソッドをオーバーライドすると、Eclipseでは常に自動追加されるのではないかと思っていましたsuper.onCreate()。これはどのように起こりますか?これを強制する抽象クラスまたは親クラスにjavaキーワードはありますか?

スーパークラスを呼び出さないことが違法かどうかはわかりませんが、これを行わなかったために例外がスローされたことをいくつかのメソッドで覚えています。これもJavaに組み込まれていますか?あなたはそれをするためにいくつかのキーワードを使うことができますか?またはそれはどのように行われますか?


これも知りたいです。また、Eclipseが役立つだけでなく、super.onCreate()の呼び出しを削除すると、アプリは「super.onCreate()を呼び出さなかった」というランタイムエラーを表示します。そうです、本当にスーパーメソッドを呼び出す必要があります。しかし、どのように?
ロドリゴカストロ

@RodrigoCastro各メソッドのjavadocを確認できます。たとえば、onCreate()

回答:


10

ソースは次のとおりです-Activity#onCreate()ほとんどすべてのコメントです(元の-行〜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;
}

したがって、私の推測では、ADTEclipseプラグインがその呼び出しを自動追加するものであるとsuper.onCreate()思います。しかし、それは完全な推測です。


2
mCalled = true例外の可能性にも使用されていると思います。おそらくそうではありませんonCreate()が、実際にそのような例外がスローされると、その単純なパターンが使用されます。
Peterdk 2010年

192

これは、サポートアノテーションライブラリに追加されます。

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

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

@CallSuper


ええ、あなたはここで頭に釘を打ちました。ありがとう。
SMBiggs 2015

まだ試していませんが、ドキュメントを読んでください。これは素晴らしいことになると思います。これは受け入れられた答えでなければなりません。
Rizwan Sohaib 2015

1
これを除いて、他のすべての答えは完全にがらくたです。受け入れられるべきです。
le_Enot 2016

3
@RizwanSohaibそれはあなたに何もすることを強制しません。強調表示され、呼び出す必要があることが通知されます。より複雑なことを行うには、注釈プロセッサを使用するか、ロジックを自分で実装する必要があります。IDEによっては、ビルドも妨げられるはずです。
frostymarvelous 2016

1
完璧な答え。
どうも

82

サブクラスに親クラスのロジックを強制的に実行させたい場合、一般的なパターンは次のようなものです。

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";
    }
}

これは、Eclipseがスーパークラス呼び出しを実装に自動的に挿入するように促すものについてのあなたの質問に実際には答えません。しかし、これはいつでも削除できるので、とにかくそれが進むべき道だとは思いません。

メソッドがJavaキーワードなどを使用してスーパークラスのバージョンを呼び出さなければならないことを実際に強制することはできません。あなたの例外は、あなたのアプローチによって無効にされた予想される不変条件、または何かをチェックする親クラスのいくつかのコードから単に来たのではないかと思います。の呼び出しに失敗したため、これは例外のスローとは微妙に異なることに注意してくださいsuper.onCreate()


8

スーパークラスメソッドも呼び出されることを絶対に確認したい場合は、少しトリックする必要があります。スーパークラスメソッドを上書きしないようにしますが、オーバーライド可能な保護されたメソッドを呼び出させます。

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();
  }
}

このように、ユーザーはSuper.foo()またはBase.foo()を呼び出す必要があり、finalとして宣言されているため、常に基本クラスのバージョンになります。実装固有のものはimpl_stuff()にあり、オーバーライドできます。


8

実際の質問に答えるために、super.onCreate()の呼び出しの自動作成はADTプラグインの機能です。Javaでは、サブクラスにメソッドのスーパー実装afaikを直接呼び出すことはできません(回避策については、他の回答で説明されているパターンを参照してください)。ただし、Androidでは、アクティビティオブジェクト(またはサービスオブジェクト)を直接インスタンス化していないことに注意してください。システムにインテントを渡し、システムがオブジェクトをインスタンス化し、(他のライフサイクルメソッドとともに)onCreate()を呼び出します。したがって、システムにはActivityインスタンスへの直接オブジェクト参照があり、onCreate()のスーパークラス実装でtrueに設定されているブール値を(おそらく)チェックできます。実装方法は正確にはわかりませんが、おそらく次のようになります。

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

そして、インテントを受け取り、そこからアクティビティオブジェクトをインスタンス化する「システム」レベルのクラスでは、次のようになります。

...
SomeActivitySubclass someActivitySubclassObject = new SomeActivitySubclass();
someActivitySubclassObject.onCreate();
if (!someActivityObject.isSuperCalled())
{
  Exception e = new Exception(...) //create an exception with appropriate details
  throw e;
}

私の推測では、それはおそらくそれよりも少し複雑ですが、あなたはその考えを理解します。便宜上、ADTプラグインが指示するため、Eclipseは自動的に呼び出しを作成します。ハッピーコーディング!


4

Javaには、superの呼び出しを強制するものはなく、望まない場合の例はたくさんあります。superの呼び出しを強制できる唯一の場所は、コンストラクターです。すべてのコンストラクターは、スーパークラスコンストラクターを呼び出す必要があります。明示的に記述しない場合は1つ(引数なしのコンストラクター)が挿入され、引数なしのコンストラクターがない場合は明示的に呼び出す必要があります。


3

Eclipseは役に立ち、必要に応じてスーパークラスの実装を呼び出すことができることを思い出させてくれます。

スーパークラスの実装を呼び出していないため、スーパークラスが行う必要のあることを行っていないため、おそらくエラーが発生しています。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.