polymorphism まとめ

Collection Framework の利用事例を紹介しつつ、クラス階層の使われ方について見てきました。

クラス階層、インタフェイスの実装に関して、ポイントをまとめておきましょう。

  • あるクラスは、親クラスや実装インタフェイスの機能を持っている(こういう性質をサブタイプと言います)。
    • だから、そのクラスのオブジェクトが、親クラスやインタフェイスとして扱われても構わない。
    • 逆に、クラスやインタフェイスで、子クラスやインタフェイスを実装するクラスを取りまとめて扱える。
  • 事例(親と子の順で)
    • Object#toString() メソッドと、TreeSet, ArrayList, Integer, MyPoint における再定義
    • Collection<Integer> インタフェイスと、ArrayList<Integer>TreeSet<Integer>
    • Comparator<MyPoint> インタフェイスと、MyPointComp0 や anonymous inner class の事例
    • Comparable<Integer> インタフェイスと Integer の事例
  • よくある利用例
    • ライブラリと利用側の橋渡し。特に、ライブラリから、利用者コードを呼ぶために利用。
    • 事例1: toString() の例
      • ライブラリ提供側: 例えば TreeSettoString() を実現する際、要素 elem の表示には elem.toString() を呼ぶ
      • 利用者側:自作クラスで独自の toString() を定義しておく
    • 事例2: Comparator<T> の例
      • ライブラリ提供側: 例えば TreeSet のソート機能は、要素比較の際は与えられた Comparator<T>compare() を呼ぶ
      • 利用者側:自分の用途にあった Comparator を定義すれば、ソート順を制御可能

余談:サブタイプ

型パラメータに関する、サブタイプではない例を紹介しておきましょう。 ちょっと込み入った話なので、興味ある人にだけ。

まずですが、サブタイプとは?ですが、

  • BA のサブタイプとは、BA の代わりに使える と言うことです。
  • Java の場合、サブクラスは、親クラスの代わりに使えるので、B extends A なら、BAのサブタイプです。
  • 基本的に、この世界では「サブ」の方が「高機能」な訳です。

でも、ArrayList<Integer>ArrayList<Object> は、互いにサブタイプではないんです。 つまり、互いに代役をこなせないんです。

ArrayList<Integer> ilist;
ArrayList<Object> olist;

olist.add(new Object()); //当然OK。
ilist.add(new Object()); //(コンパイル)エラー。つまり、ilist は olist の代わりはできない。

ilist.get(0).intValue(); // intValue() は、Integer クラスのメソッドで、OK.
olist.get(0).intValue(); // (コンパイル)エラー。つまり、olist は ilist の代わりはできない。

一般に、メソッド/関数の場合、B が A のサブタイプの場合、

  • B foo(String) は、A foo(String) の代わりに使えて、 (B A の サブタイプ関係保存)
  • String foo(A) は、String foo(B) の代わりに使える。 (B A の サブタイプ関係と逆)

となります。

一方で、ArrayList<Integer>, ArrayList<Object> を取りまとめて扱いたいときもあります。そんな時のために、

ArrayList<? extends Object> xlist; // Objectを継承した「とあるクラス」を要素にもつArrayList

という型も存在します。でも、引数に型パラメータがくるようなものは利用できなくなります。

xlist = new ArrayList<Integer>(); // OK
Object o = xlist.get(0); // OK。取得した要素は、Object のサブクラスなので、Object として扱える。
xlist.add(new Object()); // 要素の型は ? で、Object は ? のサブクラスじゃないので、型エラー

という使い方をします。