web-dev-qa-db-ja.com

オーバーライドするときにsuper()メソッドを呼び出さない場合

独自のAndroidカスタムクラスを作成するとき、そのネイティブクラスをextendします。その後、ベースメソッドをオーバーライドするときは、常にsuper()メソッドを呼び出します、常にonCreateonStopなどで行うように.

そして、最初からAndroidチームはメソッドのオーバーライドごとに常にsuperを呼び出すように勧めていたので、これだと思いました。

しかし、多くの本では、私より経験豊富な開発者が、superの呼び出しを省略していることがよくわかります。知識不足として。たとえば、この基本的な [〜#〜] sax [〜#〜] パーサークラスを見てください。superstartElementcharactersで省略されていますおよびendElement

public class SAXParser extends DefaultHandler{
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        if(qName.equalsIgnoreCase("XXY")) {
            //do something
        }
    }

    public void characters(char[] ch, int start, int length) throws SAXException {
        //do something
    }

    public void endElement(String uri, String localName, String qName) throws SAXException {
        if(qName.equalsIgnoreCase("XXY")) {
            //do something
        }else () {
            //do something
        }
    }
}

Eclipseまたは他のIDEを介してオーバーライドメソッドを作成しようとすると、superは常に自動化プロセスの一部として作成されます。

これは単純な例です。書籍は同様のコードでいっぱいです

superを呼び出さなければならないとき、および呼び出しを省略することができるときを、彼らはどのようにして知っていますか?

PS。この特定の例にバインドしないでください。これは、多くの例からランダムに選んだ例にすぎません。

(これは初心者の質問のように聞こえるかもしれませんが、私は本当に混乱しています。)

109
sandalone

superメソッドを呼び出すことにより、メソッドの動作をオーバーライドするのではなく、拡張する

superを呼び出すと、拡張するクラスがそのメソッドに対して定義したロジックが実行されます。メソッドのオーバーライドでsuperの実装を呼び出すときに重要になる可能性があることを考慮してください。例えば:

_public class A { 
    public void save() { 
         // Perform save logic
    }
}

public class B extends A {
    private Object b;
    @Override
    public void save() { 
        super.save(); // Performs the save logic for A
        save(b); // Perform additional save logic
    }
}
_

B.save()を呼び出すと、ABの両方に対して、この特定の順序でsave()ロジックが実行されます。 super.save()内でB.save()を呼び出さなかった場合、A.save()は呼び出されません。そして、super.save()の後にsave(b)を呼び出した場合、A.save()は後でB.save()で効果的に実行されます。

overridesuperの動作(つまり、その実装を完全に無視し、すべて自分で提供する)が必要な場合は、superを呼び出してはいけません。

提供するSAXParserの例では、これらのメソッドのDefaultHandlerの-​​ implementations は空であるため、サブクラスがそれらをオーバーライドして、それらのメソッドの動作を提供できます。このメソッドの javadoc でもこれが指摘されています。

_public void startElement (String uri, String localName,
    String qName, Attributes attributes) throws SAXException {
    // no op
}
_

_@barsju_がコメントで指摘したように、IDEによって生成されたコードのsuper()のデフォルト呼び出しについて、各コンストラクターにはsuper()の暗黙的な呼び出しがあります(たとえtをコードに記述します)、つまり、そのコンテキストでは、superのデフォルトコンストラクターの呼び出しを意味します。 IDEは単にそれを書き留めますが、削除した場合にも呼び出されます。また、コンストラクターを実装する場合、super()または引数を持つそのバリアント(つまりsuper(x,y,z))は最初にしか呼び出せないことに注意してくださいメソッドの。

140
Xavi López

Superを呼び出す必要があるときと、それを呼び出すことを省略できるときを、彼らはどのようにして知るのですか?

通常、特別なAPIメソッドが基盤となるフレームワークコンテキストライフサイクルに重要な意味を持っている場合、 Activity.onCreate() AP​​I documentation 。さらに、APIが堅牢な設計に従っている場合、プロジェクトのコンパイル時にコンシューマ開発者に警告するためにいくつかの例外をスローし、実行時にフォールトが生成されないことを確認する必要があります。

これがAPIドキュメントに明示的に記載されていない場合、コンシューマー開発者は、APIメソッドをオーバーライドするときに呼び出すことが必須ではないと想定することは非常に安全です。デフォルトの動作を使用する(superメソッドを呼び出す)か、完全にオーバーライドするかは、コンシューマ開発者が決定します。

条件が許可されている場合(私はオープンソースソフトウェアが大好きです)、コンシューマ開発者はいつでもAPIソースコードをチェックアウトし、メソッドが実際にどのように内部で記述されているかを確認できます。 Activity.onCreate() source および DefaultHandler.startElement() source などを確認してください。

16
yorkw

頭の中で行うべきテストは次のとおりです。

「このメソッドのすべての機能を実行してから、後で何かを実行したいですか?」はいの場合、super()を呼び出してから、メソッドを終了します。これは、バックグラウンドで多くのことを処理するonDraw()などの「重要な」メソッドに当てはまります。

(オーバーライドするほとんどのメソッドのように)一部の機能のみが必要な場合は、おそらくsuper()を呼び出したくないでしょう。

7
Michael

よくXaviはより良い答えを与えました..しかし、おそらくオーバーライドされたメソッドで呼び出されたときにsuper()が何をするか知っているかもしれません... ..

例えば:

_onDraw() 
_

ビュークラスのメソッドはオーバーライドされます。ビューが完全に描画されると、super.onDraw()と言う前に何かを描画します。したがって、ここではsuperを呼び出す必要がありますAndroidいくつかの非常に重要なことがあります(onCreate()など)

しかし同時に

_onLongClick()
_

これをオーバーライドする場合、EditTextまたは他の同様のビューのオプションのリストを含むダイアログが表示されるため、superを呼び出したくありません。それが基本的な違いです。 onCreate() , onStop()などの他のメソッドでは、OSに処理させる必要があります。

3
ngesh

のような制約配列リストを実装しました

public class ConstraintArrayList<T> extends ArrayList<T> {
  ConstraintArrayList(Constraint<T> cons) {this.cons = cons;}
  @Override
  public boolean add(T element) {
    if (cons.accept(element))
      return super.add(element);
    return false;
  }
}

コードを見ると、実際にスーパークラスにリストへの要素の実際の追加を実行させる前に、事前チェックを行うだけです。これは、メソッドをオーバーライドする2つの理由の1つを示しています。

  1. スーパークラスでできることを拡張したい拡張性
  2. 鳥の移動(ハエ)とカエルの移動(ホップ)が各サブクラスに固有である一般的な動物界の移動セマンティクスの例のように、ポリモーフィズムによって特定の動作を追加する特異性。
2
maress

Android Frameworkはsuperを呼び出す必要があり、この質問が見つかりました-2019年から現在のヒントがあります-Android Studio 3+は、必要なときに通知します

enter image description here

2
dominik

私はあなたの質問をはっきりとは知りませんでしたが、superメソッドを呼び出さない理由について質問している場合:

superメソッドを呼び出す理由があります。親クラスに引数なしのコンストラクタがない場合、そのための子クラスを作成することはできないため、引数なしのコンストラクタを保持する必要があります親クラス、またはsuper()呼び出しステートメントを子クラスコンストラクターの最上部にargument(how much argument constructor you have used in super class)で定義する必要があります。

これがお役に立てば幸いです。そうでない場合は、お知らせください。

2
Vikas Gupta