Tuesday, April 25, 2006

Using Delegate.create to maintain scope

 For those using mtasc:

If you're using mtasc you're going to need to use this special mtasc friendly Delegate class. It's also a good alternative to the built in macromedia delegate class becuase it allows for arguments.



/**
* Delegate class
* - MTASC friendly
* - allows additional parameters when creating the Delegate
*/
class Delegate
{
/**
* Create a delegate function
* @param target Objet context
* @param handler Method to call
*/
public static function create(target:Object, handler:Function):Function
{
var func = function()
{
var context:Function = arguments.callee;
var args:Array = arguments.concat(context.initArgs);
return context.handler.apply(context.target, args);
}

// Don't use local references to avoid "Persistent activation object" bug
// See: http://timotheegroleau.com/Flash/articles/scope_chain.htm
func.target = target;
func.handler = handler;
func.initArgs = arguments.slice(2);
return func;
}



What Delegate Does



Delegate is an extremely powerful tool for all OOP actionscriptors out there. If you haven't noticed already AS's scope handling blows, and oh boy it blows hard. For example:


class ScopeTest extends MovieClip{


public var myListener:Object;
public var myTest:String;

public function(Void){

myTest = "ScopeTest!";
myListener.onResize = traceSize;
Stage.addListener(myListener);
}

public function traceSize(Void):Void{
trace(Stage.width);
trace(Stage.height);

trace(myTest);
}
}



As you can see the last trace returns undefined. Wait a second, isn't traceSize a method of my instance of the object and should have the scope of the instance?

This is where Delegate comes in handy. We can force the scope of the method we're calling to be anything we want, even _root (although I wouldn't advise that, it'd be best to pass a timeline param to your class). To fix our previous scope issue we need to use Delegate.create. The syntax for Delegate.create is very simple.


Delegate.create(scope:Object, callback:Function, arg1:Type... argN:Type);


Simple right? In order to fix the event in the previous class all that needs to change is the assignment of a callback for that event.
From

myListener.onResize = Delegate.create( this, traceSize);


The final trace should now work.


Delegate is a very powerful tool, use it wisely.

0 Comments:

Post a Comment

<< Home