クロージャについてのメモ
オイラのイメージ(というか関連キーワード)は、
匿名関数
コールバック
voidポインタ
でりげーと
rubyのセミナのライトニングトークなんかで、
「lisp最強!!!」
なんて言葉を何回か聴いて、
何が最強なのか、その根拠を確かめるべく旅してます...
そーそーそーそー
たとえば、txtA.value="式"なんてときにわざわざ関数定義しなくっても
すんじゃうんだよね....
(function() { switch(v) { case 1: return 'A'; case 2: return 'B'; } return 'C'; })();
javaだとどうなるうんだっけ?
どーかなー?
(new Object() { public String toString() { switch (v) { case 1: return "A"; case 2: return "B"; } return "C"; } });
(はてなから引用)
関数内に出現する自由変数(関数内で宣言されていない変数)の解決の際、実行時の環境ではなく、関数を定義した環境の変数を参照できるようなデータ構造。
wikiによると
『典型的には、クロージャはある関数全体が他の関数(以下、エンクロージャ)の内部で宣言されたときに発生し、
内部の関数はエンクロージャのローカル変数(レキシカル変数)を参照する。
実行時に外部の関数が実行された際、クロージャが形成される。クロージャは内部の関数のコードとエンクロージャの
スコープ内の必要なすべての変数への参照からなる。』
との事。
< html> <head> <script> // ↓クロージャ状態?① function a(v1) { // ←エンクロージャ?② var v2 = 1; function b(v3) { // ← クロージャ関数?③ alert(v1 + v2 + v3); } return b; } // ↓クロージャ関数の呼び出し?④ a(1)(2); </script> </head> <body> </body> </html>
# 「エンクロージャのローカル変数」とは親関数のローカル変数や引数の事。
# レキシカルスコープが実装されていない処理系(エンクロージャが終了したら消えちゃうとか)もあるとの事。
定義はさておき(笑)、少なくとも、いわゆる親関数のローカル変数や引数を参照するニーズがあって、final修飾さ
れた変数は良く見かけるよね...
具体的な適用業務例としては、
// 超簡略化... public class Batch1 { public void unloadTable1Data(String csvFilePath) { Table1DataAccess t1da = new Table1DataAccess(); final ICsvBeanWriter csvWriter = new OCWriter(new OutputStreamWriter(new FileOutputStream(csvFilePath))); t1da.selectTable1(new Callback<Table1, Void>() { @Override public Void invoke(Table1 input) { csvWriter.write(input); return null; } }); csvWriter.close(); } } public interface Callback<INPUT, OUTPUT> { OUTPUT invoke(INPUT input); } public class Table1 { ただのValueObject ... } public class Table1DataAccess { public void selectTable1(Callback<Table1, Void> callback) { Connection con = ... PreparedStatement ps = con.prepareStatement("SELECT ..."); ResultSet rs = ps.executeQuery(); while (rs.next()) { Table1 t1 = ResultSetMapper.mapRow(rs, Table1.class); callback.invoke(t1); } } }
ビジネスロジックの一部(1行フェッチする毎の手続き)をコールバックにして、データアクセサレイヤに任すっていう、
バッチ処理で、データアクセサレイヤのクラスが、valueObject(EntityBean)のListを返して、ビジネスロジックレイヤの
クラスがくるくるなんてOutOfMelody爆なことをさせないためのフレームワーク。
csvWriterは、クロージャメソッド(←勝手に命名w)が全行処理して、最後にcsvWriter.close()する必要があるから、
必然的にエンクロージャメソッド(←勝手に命名w)のローカル変数でfinalになる...