Wednesday, December 12, 2007

ActionScript Reflection Workarounds

ActionScript has some nice reflection features. However, if you are used to Java or C# (for example) then ActionScript can seem kind of sub-par. One of the easiest things to do in Java is to create a new instance of a class dynamically:

Class<MyAwesomeClass> clazz = MyAwesomeClass.class;
MyAwesomeClass instance = clazz.newInstance();

Clearly this assumes a default constructor, but you get the picture. The equivalent in AS is:

var x:MyGreatClass;
var clazz:Class = flash.utils.getDefinitionByName("MyGreatClass") as Class;
var instance:MyGreatClass = new clazz() as MyGreatClass;
A couple of things to notice here. First, you have to declare a variable of the given type. Otherwise the AVM2 virtual machine is not smart enough to load the class and will blow up on the second line (thanks Wikipedia!) Next the standard AS Function getDefinitionByName returns an Object, not a Class, so you have to cast it. The only nice part is that you get to use the new operator with the instance variable clazz. Ah, finally we get a job-of-dynamic-language moment. To improve on this, I add a boilerplate method to my classes:

public static get clazz():Class
return MyGreatClass;

This let's me do the following:

var clazz:Class = MyGreatClass.clazz;
var instance:MyGreatClass = new clazz() as MyGreatClass;

Not quite as nice Java still, but close! The first line causes MyGreatClass to get loaded by the VM while at the same time providing a handle on the Class in question in a very convenient manner.


Ankur Mathur said...

I've been looking for some info on this for a while, so first, thanks for the post.

I do think, however that this classloading problem that requires you to declare a variable of that type at compile type kinda defeats the purpose for most applications.

Any idea if its possible to invole a method by name?

Ankur Mathur said...

I should check out how the Mate framework does this...they have a MethodInvoker that achieves this.

Typos in the post above: "compile time" not "type" and "invoke" not "invole"