Java 厨の俺にとって、引数に関数を渡す、というやり方は斬新な感覚だったのでその辺りについてメモするエントリ。
Function 型の話しに入る前に。
Array (Flex 3) のリファレンス見たとき、Java 厨的には Array#iterator() みたいなメソッドが無いのにちょっと驚いた。「お?」とは思ったけど、Array クラスだけどもプリミティブな配列みたいに[](実際は半角)でアクセスできる。
var arr:Array = ["kagami", "hoge", "foo", "bar", 123]; var i:int; for (i = 0; i < arr.length; i++) { trace(arr[i]); }
ほほぉーと思って更にリファンレス眺めてると forEach なる怪しげなメソッドを発見。ネーミング的にイテレータっぽい、何かを繰り返す的な何か、だとの予想をしつつリファンレスを読む。
forEach の項目はこうなっている。
AS3 function forEach(callback:Function, thisObject:* = null):void
配列内の各アイテムについて関数を実行します。
パラメータ
callback:Function : 配列内の各アイテムについて実行する関数です。この関数には、単純なコマンド(trace() ステートメントなど)やより複雑な演算を含めることができます。また、この関数は、次のように、アイテムの値、アイテムのインデックス、および Array オブジェクトの 3 つの引数を使用して呼び出されます。function callback(item:*, index:int, array:Array):void;
thisObject:* (default = null) : 関数の this として使用するオブジェクトです。
Array (Flex 3) より抜粋
ほほぉー。配列を処理するコードを書く、んではなくて、配列に処理するコードを渡す、という発想なのか。これは確かに面白いし、中々柔軟なやり方だなぁ、と。
というわけで Array の走査がしたい場合はこうも書ける、と。
var arr:Array = ["kagami", "hoge", "foo", "bar", 123]; arr.forEach(traceArray); private function traceArray(item:*, index:int, array:Array):void { trace("[" + index + "]" + item); }
Function 型ってのは上手く使えば何かと重宝しそうな気がしてきた。要は コールバック_(情報工学) - Wikipedia なわけだから当然といえば当然なんだけどw
俺は Java 暦が長いんで、ここまで柔軟な書き方ってご無沙汰だったのよね。でまぁ、俺は C でいう関数ポインタを思い出して segmentation fault の恐怖にちょっとブルったんだけど、とある知り合いに曰く「(引数に関数渡す書き方は)javascript ではよくあること」と言われて、あータブン AS3 の Function 型は C の関数ポインタほどピーキーな代物じゃなさそうだな、とか思いました。
さて Function 型について。正確な定義はリファレンスに譲るけど、要はメソッドの体裁を取ってればナンでも良い。
var c:CallbackTestHoge = new CallbackTestHoge(); c.foobar(); //hoge //nanntarakantara //と表示される public class CallbackTestHoge { public function foobar():void { var c:CallbackTestHoge2 = new CallbackTestHoge2; c.goFunction(printHoge); c.goFunction(nanntarakantara); } private function printHoge():void { trace("hoge"); } private function nanntarakantara(i:int=1):void { trace("nanntarakantara"); } } public class CallbackTestHoge2 { public function goFunction(callback:Function):void { callback.call(null); } }
マッタク持って無意味な実験コードで申し訳ないんだけどw Function 型の引数には、メソッドなら何でも渡せる。引数が違うと、ちと事情は異なってくるけど、デフォルト値を定義しとけば問題無く通ってしまうという柔軟っぷり。まぁ、正確な定義や使用法は Function - ActionScript 3.0 言語およびコンポーネントリファレンスガイド をちゃんと読まねばならんけど。上手いこと使いこなしてやれば、かなり便利そうな雰囲気。Observer パターン的なことがラクに書けそうね。ただ、柔軟故にコードもぐにゃぐにゃになってしまう副作用にも気をつけないといけなさそうだけど。