2010年10月02日

[java]で、匿名クラス?

で、モヤモヤの原因、匿名クラス。
GWTとかWicketで頻用している割に、理解は漫然としていたので調査。

※ソースは後述

<Test1>

(1)匿名クラスのインスタンス初期化ブロック使用

矢野さんのカッコイイ方式ですね。

Test1 ts2 = new Test1() {{a = "instance AAA"; b = "instance BBB";}};

...これは、代入式使ってるからカッコ良くないけど(笑)

(2)元クラスのprivateにはアクセスできない

Test1 ts3 = new Test1() {{a = "instance AAA"; b = "instance BBB"; c = "instance CCC";}};

private String cにアクセスしようとすると、当然怒られる。

(3)元クラスのメソッドのオーバーライド

Test1 ts4 = new Test1() {{a = "instance AAA"; b = "instance BBB";} String getD() {return "ddd";}};

...当然に問題ない。

(4)元クラスのインスタンス初期化ブロックのオーバーライド(super)

Test1 ts5 = new Test1() {{super();}};

無理...つか元々、継承側で元の初期化ブロックのオーバーライドとか出来ないのかな。
(やりたいなら継承側の初期化ブロックなりコンストラクタで変えればすむ話か...)

(5)匿名クラスでフィールド・メソッド実装&外部からの呼出

Test1 ts6 = new Test1() {String e; {e = "instance E";} String getD() {return super.getD() + "☆" + getE();} public String getE(){ return e;}};

匿名クラスでフィールド・メソッドの実装は可能(これも当然)だけど、これを外部から呼び出すのは無理。

#もしかすると方法はあるのかもしれないけど、そんなことする必要があるなら最初から普通のクラスにするべきだろう。

<TestIF>

インターフェース、抽象クラスのメソッドの実装

どちらかというと、これが匿名クラスの存在理由の大きな理由だろうねぇ。


結論。匿名クラスとは「クラス(抽象含む)・インターフェースのお手軽な継承実装インスタンス生成機構」って所ですかね〜(←長ったらしいから今後も「匿名クラス」って言うけど)。
いちいちイベント実装全てにキチンとクラス作ってインスタンス生成してね☆とか言われたら面倒で死ねるので、ないと困るけど。まぁ「気持ち悪い」と感じる人がいるのは理解できますね〜。

自分?一気にインスタンスまで生成してくれると思えばキモさは消えました。今後もバンバン使います(笑)

思うに「匿名クラス」って響きから「クラスが」動くような気がしてくるから気持ち悪さが残るのではないかなぁ。(アタマではインスタンスに決まってる!と思っても、Hoge h = new Hoge() {(...クラス実装...)}ってソースを見ながら「匿名クラス」って言われると...)

<Test1>

public class Test1 {
public String a = "a";
public String b = "b";
private String c = "c";
String d = "d";

String getD() {
return d;
}

public static void main(String[] args) {
// (1)匿名クラスのインスタンス初期化ブロック使用
System.out.println("--- ts2 ---");
Test1 ts2 = new Test1() {{a = "instance AAA"; b = "instance BBB";}};
System.out.println(ts2.a);
System.out.println(ts2.b);
System.out.println(ts2.c);
System.out.println(ts2.d);

// (2)元クラスのprivateにはアクセスできない
System.out.println("--- ts3 ---");
//Test1 ts3 = new Test1() {{a = "instance AAA"; b = "instance BBB"; c = "instance CCC";}};
//System.out.println(ts2.a);
//System.out.println(ts2.b);

// (3)元クラスのメソッドのオーバーライド
System.out.println("--- ts4 ---");
Test1 ts4 = new Test1() {{a = "instance AAA"; b = "instance BBB";} String getD() {return "ddd";}};
System.out.println(ts4.a);
System.out.println(ts4.b);
System.out.println(ts4.c);
System.out.println(ts4.d);
System.out.println(ts4.getD());

// (4)元クラスのインスタンス初期化ブロックのオーバーライド(super)
System.out.println("--- ts5 ---");
/*
Test1 ts5 = new Test1() {{super();}};
System.out.println(ts5.a);
System.out.println(ts5.b);
System.out.println(ts5.c);
System.out.println(ts5.d);
System.out.println(ts5.getD());
*/

// (5)匿名クラスでフィールド・メソッド実装&外部からの呼出
System.out.println("--- ts6 ---");
Test1 ts6 = new Test1() {
String e;
{
e = "instance E";
}

String getD() {
return super.getD() + "☆" + getE();
}

public String getE(){
return e;
}
};
System.out.println(ts6.a);
System.out.println(ts6.b);
System.out.println(ts6.c);
System.out.println(ts6.d);
System.out.println(ts6.getD());
//System.out.println(ts6.getE());
System.out.println(ts6.getClass());
//System.out.println(((TestStatic$3)ts6).getE());
}
}




<TestIF>

public class TestIF {
interface HogeIF {
String hogetter(String hoge);
}

abstract class HogeAbst {
abstract String hogett(String hoge);
}

public static void main(String[] args) {
// IFの匿名クラス
System.out.println("--- IFの匿名クラス ---");
HogeIF hif = new HogeIF() {
public String hogetter(String hoge) {
return hoge + "☆HogeIF";
}
};
System.out.println(hif.hogetter("ほげった〜"));

// 抽象クラスの匿名クラス
System.out.println("--- 抽象クラスの匿名クラス ---");
HogeAbst habst = new TestIF().new HogeAbst() {
String hogett(String hoge) {
return hoge + "☆HogeAbst";
}
};
System.out.println(habst.hogett("ほげっと"));
}

}


ラベル:java
posted by ありい at 19:54| Comment(0) | TrackBack(0) | java | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
※ブログオーナーが承認したコメントのみ表示されます。

この記事へのトラックバック
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。