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! |