yojikのlog

yojikのブログです

匿名クラスはもっと評価されていい。あの味わいはクロージャでも書けない。

http://d.hatena.ne.jp/t_yano/20061004/1159987463
昔にも書いた気がするけど、なんで皆クロージャ(とかブロック)の代用として匿名クラスを使おうとするんだろう。匿名クラスは、北欧の由緒正しきオブジェクト指向言語BETAから引き継いだ機能だし*1、クロージャ(とかブロック)の一歩先をいく可能性があったんじゃないかと思っていた。まぁ賛同者もすくないですが。*2 個人的にはJava7にはクロージャよりも匿名クラスをもっと楽に使える機能がほしかったっす。
で、話は戻ります。例えば上記の日記には「検査例外を呼び手に上手く返せない」という突っ込みが入っていますが、Closureとして渡す匿名クラス自身にerrorハンドル用のメソッドつければいいんじゃね、と思った。try catch使うよりスッキリするはず。(考えているネタと被ったらごめんなさい)
最早Closureではねーという意見もあると思いますが、やっぱ言語にあったやり方ってありますよね。

import java.io.*;
import java.net.*;
import java.util.logging.Logger;

class BreakException extends RuntimeException {}

abstract class Closure<T> {
  abstract public void execute(T value);
  public void onError(Exception e){}                 //デフォルト実装与えてみました
  public void stop() {throw new BreakException();}    //STOP機能付けてみました。
}

class IterableFile extends File {
  public IterableFile(String pathname) {super( pathname);}
  public void eachLine(Closure<String> proc)  {
    BufferedReader reader = null;
    try {
      reader = new BufferedReader(new FileReader(this));
      String line = reader.readLine();
      while(line != null) {
        proc.execute(line);
        line = reader.readLine();
      }
    } catch(BreakException ex) {
      return;
    } catch(Exception e) {
      proc.onError(e);      
    } finally {
      if(reader != null) {
        try {
          reader.close();
          Logger.global.info("**** File has been closed.");
        } catch (IOException ex) {} //close quietly.
      }
    }
  }
}
//ファイルをそのままプリントリンするけどSTOPという行を見つけたストップする
class Sample {
  public static void main(String[] args) {
    IterableFile f = new IterableFile("test.txt");
    f.eachLine(new Closure<String>() {
      public void execute(String line) {
        System.out.println(line);
        if(line.equals("STOP")) stop();
      }
      public void onError(Exception e) {
        System.out.println("ERROR発生");       
      }
    });   
  }
}

こういうコーディング、javascriptフレームワークとかでありそう。でもjavascriptだとカッコイーとかなって、Javaだとけなされちゃうんだよね。

*1:うろおぼえ

*2:もちろんローカル変数にアクセスするときに相手にfinalつけなきゃいけないとか、冗長な記法にはちょっとウンザリする面もあります。。