無名インナークラス

「開いた人が閉じる」ルール - T/O

1つのメソッド内で、数行で見渡せるように。というか、リソースのopen/closeは1箇所にまとめるようにしたいけど、それはどこまでできるかな。

ちょっと考えてみました。

Rubyにはブロックがある

Rubyのopenメソッドにはブロックを渡すと自動的にcloseしてくれる機能があるんですって

open('hoge.txt'){|f|f.each{|l|puts l}}

むりやり一行で書いたけど、なんだかよくわからないので do 〜 end で書き直し

File.open('hoge.txt') do |file|
  file.each do |line|
    puts line
  end
end

open関数の内部でブロックを実行した後、確実にcloseを呼んでくれるのだそうです。これは嬉しい。

Javaにはブロックがない

でもそのかわり、無名インナークラスっていうものがあるので、それをつかってブロックの真似事をしてみたらこんな感じになりました。

public class Main {
    public static void main( String[] args ) throws Exception {
        // open/close は全部Hogeに任せて、openとcloseの間に入る処理を
        // Blockインターフェースを実装したインナークラスとして渡す。
        Hoge.read( "hoge.txt", new Block() {
            public void execute( FileInputStream stream ) throws Exception {
                // なんか処理をする。
                // 外側にある変数も見えるよ。( final変数に限る )
            }
        });
    }
}
class Hoge {
    public static void read( String name, Block block ) {
        FileInputStream stream = null;
        
        // ファイルを開くよ
        try {
            stream = new FileInputStream( name );
        } catch (FileNotFoundException e) {
            throw new RuntimeException( e );
        }
        
        try {
            // ブロックを実行する。
            block.execute( stream );
        } catch (Exception e) {
            throw new RuntimeException( e );
        } finally {
            // 開けた人が閉じる
            try {
                stream.close();
            } catch (IOException e) {
                throw new RuntimeException( e );
            }
        }
    }
}


interface Block {
    public abstract void execute( FileInputStream stream ) throws Exception ;
}

無名インナークラスを使うと、ネストが深くなってソースが汚くなるし、「Main$1.class」みたいなクラスファイルができるので納品のときに「ソースファイルとクラスファイルの数が合わないじゃないか」と文句言われたりするし、「い」が2回続くので発音しづらいしで、とにかく人気のない可哀想なヤツっていうイメージがあります。
でも、openとcloseの部分だけを完全に隠せるのは便利だと思いました。