親から子メソッドを呼び出す理由

11119 ワード

学習の背景


効果java単品18。継承するより複合語を使うほうがいいです。には有名な例がある.
    public class InstrumentedHashSet<E> extends HashSet<E> {
        // 추가된 원소의 수
        private int addCount = 0;

        public InstrumentedHashSet() {
        }

        @Override
        public boolean add(E e) {
            addCount++;
            return super.add(e);
        }

        @Override
        public boolean addAll(Collection<? extends E> c) {
            addCount += c.size();
            return super.addAll(c);
        }

        public int getAddCount() {
            return addCount;
        }
    }

InstrumentedHashSet<String> languages = new InstrumentedHashSet<>();
languages.addAll(Arrays.asList("Java", "Ruby", "Scala"));
HashSet
public class HashSet<E>
    extends AbstractSet<E> ... {
    ...
}
AbstractSet
public abstract class AbstractSet<E> extends AbstractCollection<E> ... {
 ...
}
AbstractCollection
public abstract class AbstractCollection<E> implements Collection<E> {
    ...
    public boolean addAll(Collection<? extends E> c) {
        boolean modified = false;
        for (E e : c)
            if (add(e))
                modified = true;
        return modified;
    }
}
上記のコードを実行すると、言語でgetAddCountを使用すると、一般的に3が表示されます.しかし、実際には6です.これは、HashSetaddAllにおいて、addが重複文によってアイテム数に従って呼び出されるためである.
ここで疑問が出てきました.親クラスでメソッドを定義した場合は、親クラスのメソッドを使用する必要があります.なぜ子クラスのメソッドを呼び出すのですか?

勉強する


メソッドナビゲーション


オブジェクト向けのシステムでは,多形性により,どのような方法を実行するかを動的に決定する.このとき、実行するメソッドを選択するにはルールがあります.
  • は、まず、メッセージを受信したオブジェクトがクラスを生成するのに適した方法があるかどうかをチェックする.運転
  • メソッドがない場合は、親クラスでメソッドを探索します.
  • がトップレベルに繰り返し、メソッドが見つからない場合、異常が発生します.(Javaではコンパイルエラー)
  • self (this)


    上記の手順を実行する前に、オブジェクトがメッセージを受信すると、コンパイラはself参照という一時変数を自動的に生成し、そのメッセージを受信したオブジェクトに動作を指示します.
    静的タイプ言語に属するJavaでは,C++でthis,動的タイプ言語ではselfが主に用いられる.

    コードからメッセージを受信するオブジェクトはlanguagesです.selfは、InstrumentedHashSetを指すように設定された例を参照する.languagesaddAll()情報を送信する.languagesは、独自のクラスを生成するInstrumentedHashSetaddAll()を実行し、コードからsuper.addAll()がある.だから祖先階級の中で探求するために、直接偉人HashSetに行きます.HashSetにはaddAllを処理する適切な方法がないため、祖先の等級に従って、AbstractCollectionでaddAll()が見つかった.しかし、ここではadd()を転送する文に遭遇します.メソッドナビゲーションはself参照が指すオブジェクトから開始します.従って、このときInstrumentedHashSetadd()が存在するので、InstrumentedHashSetの方法が用いられる.

    結果


    最初は、親が親で定義されたメソッドではなく、子のメソッドを使用する理由が理解できませんでした.言葉で決まっているだけでしょう.しかし、このようにルールを決めるには原理があるに違いない.今は原理が分かった.

    リファレンス


    オブジェクト12章-多形性