匿名クラス(無名クラス)とイベントリスナー
匿名クラス(無名クラス)
内部クラス(ネストした型-内部クラス(インナークラス)(1) - 愚鈍人を参照)を使って、匿名クラスという名前の無いクラスを定義できる。
以下にその例を示す。
リスト1-匿名クラスの例(AnonymousClassSample1.java)
リスト1の変数listは一見、ArrayList<String>クラスのインスタンスのようにみえる。
しかし、実は、ArrayList<String>クラスを継承した匿名クラスのインスタンスなのである。
上記のプログラムをわかりやすいように、匿名クラスではなくクラス名を指定(ここではクラス名をAnonymousListClassとする)して記述すると、以下のようになる。
リスト2-匿名クラスをクラス名を指定して記述しなおした例(AnonymousClassSample2.java)
匿名クラスはコンストラクタを記述できない,匿名クラスを継承したクラスを作成できない等の制限がある。
そもそも名前が無いのだから、コンストラクタや継承したクラスの記述のしようがない。
しかし、匿名コンストラクタというものがあり、スーパークラスの引数付きのコンストラクタを呼び出す事は可能。(読本Java/6.5 匿名クラス - WisdomSoftを参照)
インターフェースをimplementsした匿名クラスを、記述する事もできる。
以下にその例を示す。
リスト3-インターフェースをimplementsした匿名クラスの例(AnonymousInterfaceSample.java)
このコードは、次のコードと同等である。
リスト4(AnonymousInterfaceSample2.java)
インターフェースをimplementsした匿名クラスは、 後述するGUIのイベントリスナークラスの実装によく使われる。
匿名クラスの使いみち・其の壱-オブジェクトの初期化をおこなう
匿名クラスではコンストラクタを定義する事はできないので、クラスの初期化には初期化子(イニシャライザ(initializer) ― staticイニシャライザとインスタンスイニシャライザ - 愚鈍人を参照)を使う事になる。
匿名クラスと初期化子を組み合わせると、オブジェクトの初期化をシンプルに記述する事ができる。
以下にその例を示す。
リスト5(AnonymousClassSample3.java)
このコードは、11行目~15行目の初期化子{ }内でオブジェクトの初期化をおこなっている。
コレクションクラスだけだけではなく、通常のクラスの初期化にも使える。
以下にその例を示す。
リスト6(AnonymousClassSample4.java)
14行目の{{ }}の部分は一見、奇妙にみえるが、実は内側の{ }の部分で初期化子を使ってクラスのメンバーの初期化をおこなっているだけ。
変数iとjはprotectedなのでクラス外部から変数を変更できないが、初期化子はクラスの内部なので変更が可能(MyClassが仮に別packageに定義されていたとしても)。
C#ではオブジェクト初期化に専用の構文が用意されている。
(オブジェクト初期化子とコレクション初期化子 (C# プログラミング ガイド))
匿名クラスの使いみち・其ノ弐-イベントリスナーの記述
匿名クラスはandroidやswing等のGUIのイベントリスナーの記述によく使われる。
androidのイベント処理については、「ウィジェットのイベント処理 - 愚鈍人」 で述べているので、ここではswingのプログラムの例を示す。
android同様、swinのイベント処理では、 ウィジェットにイベント処理を記述したクラス(イベントリスナーインターフェースを実装したクラス)のインスタンスをセットする事により、 イベントの処理コードとその対象となるウィジェットを結びつける。
ボタンが押された時のイベントをbuttonにセットするには、以下のようにaddActionListenerメソッドを使って、ActionListenerインターフェースを実装したクラスのインスタンスをセットする。
リスト7(Sample1.java)
このコードは匿名クラスを使うことにより、以下のよう簡潔に記述できるようになる。
リスト8(Sample2.java)
C#には、ローカルクラスが無いので、イベントの処理をこのような形で記述する事はできない、
デリゲート(関数のポインターのようなもの)というjavaには無い仕組みを使ってイベントを記述する事になる。
デリゲート (プログラミング) - Wikipedia ,イベント (C# によるプログラミング入門)等を参照。