Java : ローカルクラスを使いこなせ!
ついこの間まで、ローカルクラスの存在を知らなかった私([id:lethevert:20060115:p3]のコメント欄参照)が言うのもなんですが、関数的な方もメッセージ指向の方も、あまりJavaを甘く見ないほうがいいかもしれないです。
Javaは、非常に純粋なオブジェクト指向言語であり、かつ、構文糖衣([id:lethevert:20060111:p1]参照)に対して非常に保守的であることに加えて、ユーザー(つまりプログラマ)が大衆化されていることから、その力量を見誤られがちな気がしますが、特長をよくつかんでやれば、なかなか引けを取らない言語ですよ。
-
-
- -
-
次の例は、ストリームからオブジェクトの配列を読み込む処理をローカルクラスと無名クラスの組み合わせで書いたものです。ストリームから要素数を取り出して、配列を作成する処理は、全ての種類のオブジェクトで共通なので、ローカルクラスに抜き出して共通化し、個別の処理だけを、無名クラスで実装しています。
関数型言語になれた方なら、こういう書き方は見慣れたやり方だと思いますが、Javaでも同じようなことがかけるという例です。
class OuterClass { public Object[] readStream (int type, final ObjectInputStream is) throws IOException { /* 汎用的なストリーム読み込み手続きのクラス */ abstract class C { Object[] allObjects() throws IOException { int n = is.readInt(); Object[] objs = new Object[n]; for (int i=0; i<n; ++i){ objs[i] = each(); } return objs; } abstract Object each() throws IOException; } /* 本体部 - typeで読み込むオブジェクトの種類を切り替える */ switch(type){ case 0: return new C() { Object each() throws IOException { return DataClass0.readStream(is);} }.allObjects(); case 1: return new C() { Object each() throws IOException { return DataClass1.readStream(is);} }.allObjects(); case 2: return new C() { Object each() throws IOException { return DataClass2.readStream(is);} }.allObjects(); default: return null; } } }