web-dev-qa-db-ja.com

なぜAndroidで時々superを呼び出さなければならないのですか?

メソッドをオーバーライドすると、次のように初めて呼び出されたときに例外が発生することがあります。

_05-31 21:32:04.266: E/AndroidRuntime(28471): Android.support.v4.app.SuperNotCalledException: 
Fragment AnalFragment{41795860 #1 id=0x7f070002} did not call through to super.onDestroy()
_

なぜsuper.method()を呼び出さなければならないのですか?親クラスによる義務があることは理にかなっていますが、さらに重要なことは、メソッドがクラッシュするのを待つのではなく、superを呼び出す必要があることをどのように知るのでしょうか?

41
StackOverflowed

なぜsuper.method()を呼び出さなければならないのですか?

Android SDKは非常に複雑になる可能性があります。たとえば、アクティビティとフラグメントの両方が適切に機能するために多くの操作を実行する必要があります(ライフサイクルの管理、メモリ使用量の最適化、レイアウトを画面に描画するなど)クライアントに基本クラスを呼び出すことを要求する(多くの場合、メソッドの最初に)ことにより、開発者に妥当なレベルの抽象化を提供しながら、これらの操作が実行されることが保証されます。 。

どのように私たちはそれを知っていますか 関数 method superを呼び出す必要がありますか?

ドキュメントには、これが必要かどうかが記載されているはずです。サンプルコードをGoogleで検索しない場合(またはAPIデモをチェックする...またはそれ以上の場合は、ソースコードをご覧ください!)。理解するのはそれほど難しくないはずです。

41
Alex Lockwood

私はこれがOPの真の意図ではないことを知っています、彼はこの質問をしました、そして非常に良い答えを得たとは思いません。彼らはそれを必要とするでしょう、なぜ彼らは私のためにそれをしないのですか!!!」その質問に対する答えは次のとおりです。

基本的に、super()は、呼び出す必要のあるものをオーバーライドする場合に呼び出す必要のあるものであり、かなり複雑なコードになることがよくあります。さて、彼らがあなたのためにそれをして、あなたの関数の前にそれを呼び出すだけではない理由は、主にあなたがコントロールできるようにするためです! :-D

具体的には、super()を呼び出す場合は制御できませんが、WHEN!したがって、super()が呼び出される前に発生する必要がある特定のコードがあるとしましょう。コードを実行した後にのみsuper()を呼び出すことができます。または...コードがクラッシュしないようにsuper()がすでに実行されている必要があるとします。コードを実行する前にsuper()を実行するオプションがあり、すべてがセットアップされていることを確認できます。要するに、技術的にはスーパークラスのハードコアをオーバーライドして、super()自体を処理する独自のメソッドをコーディングすることもできます。これをする! :-P

したがって、「なぜsuper()を呼び出さなければならないのか」に対する簡単な答えは...です。これにより、super()が実行される前または後に呼び出され、処理を実行できます。 :-)

14
Jared

superキーワードには、主に2つの用途があります

1。スーパークラスのコンストラクターを呼び出します。

2。サブクラスのメンバーによって隠されているスーパークラスのメンバーにアクセスします。

だから、なぜスーパーキーワードを時々使用する必要がありますか?答えはAndroidは4GL言語の下にあります。つまり、多くの機能が用意されています。カスタマイズのためにこれらのメソッドをオーバーライドしている間、superキーワードを使用します。

Android(ほとんどの場合そうするように)のスーパーキーワードの非常に簡単な使用法を参照してください。

@Override
public void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);
    .
    .
    .
}

super()は、常にサブクラスのコンストラクター内で実行される最初のステートメントでなければなりません。サブクラスがsuper()を呼び出すとき、そのすぐ上のスーパークラスのコンストラクターを呼び出しています。スーパーの2番目の形式は、サブクラスのメンバー名がスーパークラス内の同じ名前のメンバーを隠す状況に最も適しています。

9
Lucifer

通常、要件はAPIドキュメントで直接指定されます。たとえば、Android.widget.ListView.onFinishInflateを参照してください。

保護されたvoid onFinishInflate()

...

サブクラスがonFinishInflateをオーバーライドする場合でも、呼び出されるように、必ずスーパーメソッドを呼び出す必要があります。

残念ながら、私の個人的な経験では、Android docsの品質は不均一です。そのため、そのように文書化されていない通話が必要な場合があると思います。

3

メソッドをオーバーライドすると、基本的には親クラスにあるものはすべて無視し、代わりに子クラスに独自のカスタム実装を追加することに注意してください(文字通り上書きします)!

この場合、親実装を破棄したくありません。実際に元のメソッドを引き続き使用し、各子クラスに追加のチェックを個別に追加します。

ここで「スーパー」キーワードを使用します!

「スーパー」キーワードを使用し、その後にドット、次にメソッド名を使用することにより、子クラスで親メソッドを再利用できます。

例:isValidMove(position)は、チェスの駒のためのメソッドであり、移動の有効性を確認し、8x8チェスボードでバインドされています。

super.isValidMove(position);

ここでキーワードsuperを使用することは、「this」クラスの実装内からスーパー(または親)クラスの実際のメソッドを実行することを意味します。

つまり、各子クラスで、カスタム動作を確認する前に、super.isValidMove(position)がfalseを返したかどうかを確認できます。その場合、それ以上のチェックを行う必要はなく、すぐにfalseを返します。それ以外の場合は、チェックを続けます。

Rookクラスの新しい実装は次のようになります。

class Rook extends Piece{
   boolean isValidMove(Position newPosition){
      // First call the parent's method to check for the board bounds
  if(!super.isValidMove(position)){
     return false;
  }
  // If we passed the first test then check for the specific rock movement
  if(newPosition.column == this.column && newPosition.row == this.row){
     return true;
  }
  else{
     return false;
      }
   }
}

Super()を使用して、親のコンストラクターを呼び出すこともできます。これは通常、子のコンストラクタを実装するときに行われます。通常、最初にすべてを親のコンストラクターで実行し、次に子のコンストラクターにコードを追加します。

class Rook extends Piece{
   // default constructor
   public Rook(){
    super(); // this will call the parent's constructor
    this.name = "rook";
   }
}

注:子のコンストラクターがsuperを使用して親のコンストラクターを明示的に呼び出さない場合、Javaコンパイラーは親クラスのデフォルトコンストラクターへの呼び出しを自動的に挿入します。親クラスにデフォルトがない場合コンストラクターでは、コンパイル時エラーが発生します。

1
Rahul Joshi

基本的に、superは、クラスの拡張が行われる(最初のクラス定義でextendsを使用)またはインスタンスが作成されるメインのスーパークラスフィールド/メソッドを参照するために使用されるメソッドです。

目的を解決するために使用されるスーパークラスのメソッド/フィールドの最も基本的な定義を変更する必要がある場合。

例えば

Java.lang.Object(多くのメソッドとフィールドがあります)> Android.view.View> Android.view.ViewGroup> Android.widget.LinearLayout

ただし、オブジェクトクラスのメソッドであるため、変更/使用する必要がある場合は、SuperLayoutがLinearLayoutクラス内のオブジェクトクラスで最初に作成されたメソッドを参照する必要があります。

0
Rahul Joshi