話のネタを仕入れたはいいものの、使いどころに困ってはいませんか?
バーでの会話で話題に絡めた小洒落た話を咄嗟にひろげられると粋ですよね。
内部クラスの階層の話ではクラスにも階層があるね、というお話でした。
今回はそのエンクロージング内部クラスの使いどころのお話です。
プログラミングというのは美術などと同じく、画材を知ったからと言って即、作品になるわけではありません。
新しい道具を得たからと言って、それを使ってどう新しい創作をするかというのは難しい問題です。
エンクロージング内部クラスは親のインスタンスへアクセスを許可された特別なクラスですが、
では、どういったときにこの特権を使えばいいのでしょうか?
今回はそのサンプルを挙げてみようと思います。
内部クラスのメリットは、外部クラスと秘密のやり取りができるというところです。
外部クラスはそのさらに外に情報を公開することなく、しかし、内部クラスとやり取りができるのです。
これは、情報の隠ぺいをうまく行いたいという要望にある一定の答えを与えてくれるのです。
staticな内部クラスをComparatorの実装として使う
staticな内部クラスをjava.util.Comparatorの実装として使ってみましょう。
import java.util.Comparator;
public class Piyo {
private int param1;
private int param2;
/** param1の昇順に並べるComparator */
public static class Param1Comparator implements Comparator<Piyo> {
public int compare(Piyo o1, Piyo o2) {
return o1.param1 - o2.param1;
}
}
/** param2の昇順に並べるComparator */
public static class Param2Comparator implements Comparator<Piyo> {
public int compare(Piyo o1, Piyo o2) {
return o1.param2 - o2.param2;
}
}
}
このサンプルコードでは、Piyoクラスのprivateなフィールド2つを利用したComparatorをstaticな内部クラスとして実装しています。
このComparatorを使うことでPiyoクラスをparam1順に並び変えることもできれば、param2順に並び変えることもできるのです。
public static void main(String[] args) {
List<Piyo> piyoList = new ArrayList<Piyo>();
Collections.sort(piyoList, new Piyo.Param1Comparator());
}
このように、Piyoクラスのprivateなフィールドparam1を利用したComparatorを内部クラスで作ることで、
Piyoクラスは外部に向けて該当フィールドを公開することなくPiyoクラスと密なやり取りをするComparatorを作ることに成功しました。
このように、なんらかのInterfaceの実装を作る必要があるけども、その実装が一通りとは限らないという状況で、内部クラスは非常に便利です。
エンクロージング内部クラスをIteratorの実装として使う
次は内部にListを持っているHogeクラスを考えます。
このHogeクラスに中心からの距離が一定の範囲内のPointだけを返すIteratorを実装したいと思います。
import java.awt.Point;
import java.util.Iterator;
import java.util.List;
public class Hoge {
List<Point> pointList;
/** 中心からの距離でフィルタリングしたIterator */
public class FilterIterator implements Iterator<Point> {
private double dis;
private int index;
public FilterIterator(double dis) {
this.dis = dis;
}
public boolean hasNext() {
for (; this.index < Hoge.this.pointList.size(); this.index++) {
Point p = Hoge.this.pointList.get(this.index);
if (p.x * p.x + p.y * p.y <= this.dis * this.dis) {
return true;
}
}
return false;
}
public Point next() {
return Hoge.this.pointList.get(this.index);
}
public void remove() {
throw new UnsupportedOperationException();
}
}
}
FilterIteratorはHogeクラスのprivateなフィールドを参照して値を返すIteratorです。
Hogeクラスは外部に対してListのフィールドを公開していません。
しかし、Iteratorなどのインターフェースの実装は時に別クラスとして実装せざるを得ない場合があります。
こういう時に内部クラスを活用すると隠ぺいを保ちつつ、実装クラスを提供できるのです。
Hoge hoge = new Hoge();
Iterator<Point> ite = hoge.new FilterIterator(10);
外部から使う場合は、対象となるHogeクラスのインスタンスに".new"をつけてインスタンスを生成します。
いかがだったでしょうか。内部クラスの使い道がいまひとつ分からないという方への道しるべになれば幸いです。
投稿日時 : 2007年8月1日 23:30