Class locations in AS2.0 run-time

I hadn’t really thought about where AS2.0 classes reside at run-time until I encountered a need to dynamically create instances of the classes I had made for one of my current projects. In AS1, it was really simple to dynamically create instances from a class name, because you specified where the class definition resided, for example:

// on _root
function MyClass() { };
// anywhere else:
className = "MyClass";
myInstance = new _root[className]();

However, in AS2.0, you never specify where the class definition sits – it’s really pretty obvious though, if you think about it for a moment. AS2.0 classes can be accessed by name from anywhere in the swf – they are accessible globally. This , of course, is because they reside inside of _global. For instance, if you defined a custom class called “MyClass” in AS2, you could access it at _global.MyClass, and could create instances of it dynamically with:

className = "MyClass";
myInstance = new _global[className]();

Simple, eh? So what about classes inside of packages? Well, the dot notation indicates an object hierarchy, and it turns out that’s all there is to it. The class definition for a class called “MyClass” inside the “com.gskinner.utilities” package can be found at _global.com.gskinner.utilities.MyClass. If you knew the package was always the same, you could create instances dynamically with:

myInstance = new _global.com.gskinner.utilities[className]();

If you want to create instances from full dynamic class names with varying packages, you can use this function I whipped up:

function getInstanceOf(p_fullName:String):Object {
var classPath:Array = p_fullName.split(".");
var package:Object = _global;
var l = classPath.length-1;
for (var i:Number=0;i<l;i++) {
package = package[classPath[i]];
}
var c:Function = package[classPath[classPath.length-1]];
var instance:Object = new c();
return instance;
}
// test it:
myInstance = getInstanceOf("com.gskinner.utilities.MyClass");

Unfortunately, I haven’t got it working with .apply yet, so you can’t pass arguments to the constructor (if anyone gets this to work, send it to me, and I’ll post it).

All of this raises an important consideration: Be careful of name conflicts with packages when adding items to the _global object (classes should be fairly safe due to their capitalization)! If you have a class “com.gskinner.utilites.MyClass”, and you then you define a _global.com variable, you will overwrite the entire “com” class package (Eek!). For example:

import com.gskinner.utilities.MyClass;
_global.com = 127;
myInstance = new com.gskinner.utilities.MyClass();
// myInstance is undefined!

Grant Skinner

The "g" in gskinner. Also the "skinner".

@gskinner

3 Comments

  1. This was my first attempt too, back in the ages 🙂 but some times later i recognized, that a simple eval does the same.

    Additionally you can return a reference to the constructor instead of the instance.

    This enables Mr. Q to use parameters.

    Have nice day,

    bokel

  2. i was about to say the same thing as bokel has…

    new eval(theClass)() achieves the same thing… using ‘apply’ to dynamically assign arguments, afaik won’t work.

    to use apply, you need an object to “apply” on… an object is already constructed

  3. Hi Grant,

    This does not seems to work for me… the instance keeps being undefined…any idea?

Comments are closed.