2010-11-18 26 views
60

新しいActivityクラスを作成してonCreate()メソッドをオーバーライドすると、私はいつも自動追加されます:super.onCreate()私は不思議に思っていました。これはどうやって起こるのですか?これを強制する抽象クラスまたは親クラスにjavaキーワードがありますか?派生クラスが強制的にスーパーメソッドを呼び出す方法

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

+0

@CallSuper

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

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

私もこのことを知ってほしいです。そして、Eclipseが役に立つだけでなく、super.onCreate()への呼び出しを取り除くと、「super.onCreate()」を呼び出さなかったというランタイムエラーが発生します。そう、本当にスーパーメソッドを呼び出す必要があります。しかしどうですか? –

+0

@RodrigoCastro各メソッドのjavadocsを確認できます。たとえば、[onCreate()](http://developer.android.com/reference/android/app/Activity.html#onCreate(android.os.Bundle))。 –

答えて

9

はここActivity#onCreate()の源だ - それは、ほとんどすべてのコメント(original - see line ~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; 
} 

ので、私の推測では、ADT Eclipseプラグインがあなたのためにsuper.onCreate()にそのコールを自動的に追加する何であるということでしょう。しかし、それは全体的な推測です。

+0

'mCalled = true'も例外であると考えられます。おそらく 'onCreate()'ではないかもしれませんが、本当にそのような例外がスローされると、その単純なパターンを使用します。 – Peterdk

3

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

3

Eclipseは役に立ちます。必要に応じてスーパークラスの実装を呼び出すことができます。

あなたは実装を呼び出さないため、スーパークラスが必要とする何かをしていないため、おそらくエラーが発生します。

7

superclass-methodが確実に呼び出されるようにするには、ちょっとトリックする必要があります。スーパークラスメソッドを上書きしないで、オーバーライド可能な保護メソッドを呼び出させます。

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()、それが最終的として宣言されたとして、それは常に基本クラスのバージョンになります。実装固有のものはimpl_stuff()にあり、上書きすることができます。

71

あなたは親クラスのロジックを実行するためにサブクラスにしたい場合は、一般的なパターンは、次のようなものです:

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

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

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

と意図を受信し、それから、Activityオブジェクトをインスタンス化し、「システム」レベルのクラスで:

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

私の推測によれば、それはおそらくそれより少し複雑ですが、あなたはそのアイデアを得るでしょう。 Eclipseは、便利なように、ADTプラグインから通知されるため、自動的にコールを作成します。ハッピーコーディング!

134

これは、支持アノテーション・ライブラリに追加されます。

+0

ねえ、あなたはここの頭に釘を打つ。ありがとう。 –

+0

まだ試していませんが、ドキュメントをお読みください。これは私が推測する素晴らしいだろう。これは受け入れられた答えでなければなりません。 –

+0

申し訳ありませんが、私のコメントを変更する必要があります。それはスーパーメソッドを実装するように強制されませんでした。私は夕食の呼び出しなしでアプリを実行することができました。 –

関連する問題