FunctionにDisられた

Functionのさわやかさを語らせたら地域一、でおなじみの片山です。

表題のFunctionですが、皆さん意図せずともinvokeしまくっているかと思います。
私もご多分に漏れず呼びまくっていますが、最近引数の数が違うのにFunctionが呼べてしまうという事態に陥りました。


ソースは長いのでこちらにおいておきます。
やっているのは、

に対して、それぞれを引数0個、引数1個(正しい型)、引数2個(第一引数は正しい型)、引数1個(異なる型)を使って呼び出すというテストです。

結果を書くと、こうなります。

  引数0個 引数1個(正しい型) 引数2個(第一引数は正しい型) 引数1個(異なる型)
引数0メンバメソッド × × ×
引数1メンバメソッド × × ×
引数0ローカルメソッド
引数1ローカルメソッド × × ×


ここで注目すべきなのは、「引数0のローカルメソッドは、どんな引数の場合でも呼び出しに失敗しない」という点です。
従って、例えば「あるFunctionが渡されたときに、そのFunctionが引数ありの場合はコールバックしてもらって、引数なしなら処理続行」という仕様にしたい場合、

public function invoke(f:Function):void{
  var callBack:Function = function():void{
     //続行処理
  };
  try{
     f(callBack);
  }catch(e:Error){
     //失敗したらコールバックなし
     f();
     callBack();
  }
}

引数のFunctionがローカルメソッドかメンバメソッドかによって、挙動が変わってしまいます。

public function execute():void{
   invoke(member);
   invoke(function():void{ trace("local"); });
}  
public function member():void{
   trace("member");
}
public function invoke(f:Function):void{
   var callBack:Function = function():void{
      trace("GJ");     
   };
   try{
     f(callBack);
   }catch(e:Error){
     trace("invoke fail.");
     //失敗したらコールバックなし
     f();
     callBack();
   }
}

これのexecuteを実行すると、

invoke fail.
member
GJ
local

従ってこういう実装をする場合は、引数が少ない順に試していく実装の方が確実な模様です
最近ハマりましたので。。。