views:

151

answers:

2

I have an array of function callbacks, like this:

class Blah {
    private var callbacks : Array;

    private var local : Number;

    public function Blah() {
        local = 42;

        callbacks = [f1, f2, f3];
    }

    public function doIt() : Void {
        callbacks[0]();
    }

    private function f1() : Void {
        trace("local=" + local);
    }

    private function f2() : Void {}
    private function f3() : Void {}

}

If I run this code, I get "local=undefined" instead of "local=42":

blah = new Blah();
blah.doIt();

So, Flash function pointers don't carry context. What's the best way to solve this problem?

+1  A: 

Try:

callbacks[0].apply(this, arguments array)

or

callbacks[0].call(this, comma-separated arguments)

If you want to "carry context" try :

public function doIt() : Void {
    var f1() : function (): Void {
        trace("local=" + local);
    }

    f1();
}

This creates a closure on this.local as expected

Vlagged
+1  A: 

the most easy way is to use the Delegate class ... it works using the techniques Vlagged described ... although i must amend, that i do not understand the code at all (it is also syntactically incorrect) ...

otherwise, try this:

class AutoBind {
    /**
     * shortcut for multiple bindings
     * @param theClass
     * @param methods
     * @return
     */
    public static function methods(theClass:Function, methods:Array):Boolean {
     var ret:Boolean = true;
     for (var i:Number = 0; i < methods.length; i++) {
      ret = ret && AutoBind.method(theClass, methods[i]);
     }
     return ret;
    }
    /**
     * will cause that the method of name methodName is automatically bound to the owning instances of type theClass. returns success of the operation
     * @param theClass
     * @param methodName
     * @return
     */
    public static function method(theClass:Function, methodName:String):Boolean {
     var old:Function = theClass.prototype[methodName];
     if (old == undefined) return false;
     theClass.prototype.addProperty(methodName, function ():Function {
      var self:Object = this;
      var f:Function = function () {
       old.apply(self, arguments);
      }
      this[methodName] = f;
      return f;
     }, null);
     return true;
    }
}

and add this as the very last declaration in Blah:

private static var __init = AutoBind.methods(Blah, "f1,f2,f3".split(","));

that'll do the trick ... note that calls to f1, f2 and f3 will become slower though, because they need one extra function call ...

back2dos
thanks but this seems a little overkill
superjoe30

related questions