オーバーライドするときにsuper()メソッドを呼び出さないのはいつですか?


113

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

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

しかし、多くの本では、自分よりも経験豊富な開発者が電話superを省略していることがよくあり、知識の欠如として電話をかけていることを本当に疑っています。たとえば、とで省略されている次の基本的なSAXパーサークラスを見てください。superstartElementcharactersendElement

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。この特定の例に束縛しないでください。これは、多くの例の中からランダムに選んだ一例にすぎません。

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


3
endElementのAPIドキュメントには、「デフォルトでは何もしない。アプリケーションの作成者はこのメソッドをオーバーライドする可能性があります...」とあります。つまり、「何もしない」ため、superを安全に呼び出すことができます。そのメソッドのドキュメントを読んだ場合、する必要があるか、できないか、するべきではないか、ということがよくわかります。
zapl

1
小さな例:私はスプラッシュ画面でonBackPressed()を使用しています。スプラッシュから抜け出さないようにsuperを呼び出さないでください。ボタンを無効にするだけです。
Bojan Kogoj

@sandaloneここで質問して申し訳ありませんが、アプリ内課金でVAT税を処理する方法、およびGoogleによって自動的に行われる国、および手動でVAT税を報告/支払う必要がある経験はありますか?stackoverflow.com/questions/36506835/…を
Vidar Vestnes

回答:


144

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()save()ロジックを実行します。あなたが呼び出していなかった場合は内部に、呼び出されないでしょう。そして、あなたが後に呼ばれたら、効果的にその後に行われるでしょう。ABsuper.save()B.save()A.save()super.save()save(b)A.save()B.save()

の動作をオーバーライドする 場合super(つまり、その実装を完全に無視してすべて自分で提供する場合)は、を呼び出さないでくださいsuper

SAXParserあなたが提供する例、実装DefaultHandlerこれらの方法については、サブクラスはそれらをオーバーライドして、これらのメソッドの動作を提供できるようにすることを、単に空です。このメソッドのjavadocでは、これも指摘されています。

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

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


14
また、コンストラクターsuper()(スーパークラスのデフォルトコンストラクター)は、指定しなくても常に呼び出されることに注意してください。スーパークラスにデフォルトのコンストラクターがない場合、スーパークラスのコンストラクターの1つをサブクラスコンストラクターの最初のステートメントとして明示的に呼び出さないと、コンパイルエラーが発生します。
barsju

1
うん、それは基本的にただの怠惰です-私たちが知っている方法では何もしないことを簡潔にするために単にそれを省略します
Voo

1
貴重なコメントをありがとう、@ barjsu、これらの詳細を回答に含めました。
XaviLópez2012

16

いつスーパーに電話をかけなければならないのか、いつ電話を省略できるのか、彼らはどうやって知るのですか?

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

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

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


補足説明をありがとうございます。ソースコードを確認するように言ってくれてありがとう。
サンダロン

7

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

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

一部の機能のみが必要な場合(オーバーライドするほとんどのメソッドと同様)、おそらくを呼び出したくありませんsuper()


3

さて、シャビはより良い答えを与えました..しかし、おそらくsuper()オーバーライドされたメソッドで呼び出されたときに何が行われるかを知っているかもしれません...それはデフォルトの動作で何をしたかを広告します。

例えば:

onDraw() 

上書きビュークラスのメソッド..あなたはそれがビューが完全に描画された後..ので、ここでの呼び出しが表示されます)super.onDrawを(言って前に何かを描くsuper()(のonCreateのような)ので、必要であるアンドロイド行うにはいくつかの非常に重要なものを持ってい

しかし同時に

onLongClick()

これをオーバーライドするときは、スーパーを呼び出さないでください。これは、EditTextまたは他の同様のビューのオプションのリストを含むダイアログが表示されるためです。それは、基本的な差分です。onCreate() , onStop()OSにそれを処理させるような他のメソッド。


2

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

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

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


2

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

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

Android Frameworkのどのオーバーライドされたメソッドを呼び出しsuperてこの質問を見つけるべきかについても疑問に思った方のために、2019年の最新のヒントを以下に示します。AndroidStudio 3以降では、必要なときに通知されます

ここに画像の説明を入力してください

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