ClassFinder class
Thursday, 10 March 2005In a recent project I needed to instantiate a number of objects of various classes based on configuration data coming from an XML file. Unfortunately instantiating a class at runtime is not straight forward if all you’ve got to work with is a string. What I needed was some way of getting a reference to the constructor function of a class given the fully qualified class name. Ten minutes of tinkering later, I came up with the ClassFinder class.
class com.dynamicflash.utils.ClassFinder { public static function find(package:String) : Function { var packageParts:Array = package.split(".") var obj:Object = _global; for (var i:Number = 0; i < packageParts.length; i++) { obj = obj[packageParts[i]]; } return Function(obj); } }
Feeding the ClassFinder.find() method with a fully qualified class name will return a reference to the constructor of the class. You can use this to instantiate an object of that class using new and passing any arguments to the constructor as you would normally.
import com.dynamicflash.utils.ClassFinder; var myClass:Function = ClassFinder.find("com.dynamicflash.SomeClass"); var instance = new myClass("Test");
Classes are stored in _global with nested objects representing the package hierarchy. All ClassFinder.find() does is split the package name into chunks and descent the nested objects one at a time to find the class constructor function.
So what’s the catch? Because of the way the Flash compiler works, any classes that aren’t explicitly referenced in any of your code at compile time will not be included in the SWF. This means that ClassFinder won’t be able to find them, returning undefined instead. If you want to trick the compiler into including such classes, you need to make a dependancy link to those classes from a class that is explicitly referenced in your code.
class com.dynamicflash.SomeOtherClass { public function SomeOtherClass () { ... } // Create dependancy link private static var SomeClassDependancy = com.dynamicflash.SomeClass; }
This method is used in Macromedia’s V2 component core classes to make sure they’re all included in the SWF if just one of them is referenced.
–Update–
I’ve just realised that a very similar class is included with Flash MX 2004 Professional, but adding it to your projects isn’t exactly intuitive. You have to open up the Classes common library (via Window » Other panels » Common libraries » Classes in the main menu) and drag the UtilsClasses symbol into your library. You can then use
mx.utils.ClassFinder.findClass() instead of my class.
Why Macromedia didn’t just put these classes in the standard folder I don’t know, but since using it requires extra work I’ll stick with my version of ClassFinder.








I totally agree there, it's amazing just how these useful
Richard Leggett | Friday, 11 March 2005 | 1:04 amI totally agree there, it’s amazing just how these useful classes aren’t documented (such as XPath). We had someone ask about it here: http://flashmove.com/forum/showthread.php?t=17266
Apparently the guy re-wrote it too, must ask what happened to that re-write! I linked to another post on there that may be of interest to you as it’s kinda related, finding which class an object is an instance of (especially good for MovieClips), about halfway down the post.
Excellent tip about the class dependency with static member btw!
Thanks Richard. I'll have a look at this later.
Steve | Friday, 11 March 2005 | 9:36 amThanks Richard. I’ll have a look at this later.
Using dependancy links to classes also increases the swf filesize
Bob Donderwinkel | Friday, 11 March 2005 | 12:26 pmUsing dependancy links to classes also increases the swf filesize for each class included. So what’s your aim exactly with runtime instantiating the classes with xml, unless you know already which classes you are going to use?
It would mean you have to include each class as a dependancy in the swf manually in any case, negating the runtime instantiating benefit perhaps. And if you would use a basic class making dependancy links to all classes you could possibly need, the filesize could get bigger then needed since you perhaps wont use all the classes.
Nice work though. I’m guessing your ClassFinder is more streamlined then mx.utils.ClassFinder :).
Why aren't you just using eval? var myClass:Function = Function(eval("fullyQualifiedClassName")); I mean,
Simon Wacker | Friday, 11 March 2005 | 12:45 pmWhy aren’t you just using eval? var myClass:Function = Function(eval(”fullyQualifiedClassName”)); I mean, you do not do any extra checking whether a class with the given name does even exist and that like. You are also not checking whether the passed-in class name is null or undefined. The as2lib does also offer that functionality together with a lot more. Take a look at the Reflection API (org.as2lib.env.reflect). Note that the current version is rather heavy weight. We are going to release an improved and lighter reflection api (together with as2lib 0.1 final) in about 1 month.
@Bob: I'm not too worried about file size here as
Steve | Friday, 11 March 2005 | 1:57 pm@Bob: I’m not too worried about file size here as the classes I’m choosing between are very lightweight. The reason I need runtime instantiation is that I don’t know which of my classes I need to instantiate until I load the class name from the configuration XML file.
@Simon: Though eval() would indeed work, I try to avoid using it wherever possible. I can’t really explain why, it just feels a little dirty
Having said that (and without checking )I guess using eval() would make ClassFinder more efficient, but unless you’re instantiating thousands of objects this way it wouldn’t really be noticable.
Right. If file size would be an issue you could
Bob | Monday, 14 March 2005 | 10:58 amRight. If file size would be an issue you could perhaps load the dependancy classes in the main swf through a seperate swf, specified by the XML.
That would allow for dynamic updating of the main swf, and a smaller file size as well :).
Bob: Absolutely! In fact, we're going to be doing just
Steve | Monday, 14 March 2005 | 1:18 pmBob: Absolutely! In fact, we’re going to be doing just that for our application just as soon as we ship the new version. Now if only I could find an efficient (both byte- and processor-wise) component set with a DataGrid replacement, I’d be laughing.
"Though eval() would indeed work ... it just feels a
Dave | Wednesday, 29 March 2006 | 12:37 pm“Though eval() would indeed work … it just feels a little dirty”
I know what you mean, but why make work for yourself? As long as code strikes a good balance between readability and efficiency it shoud be a go-er…
Great site by the way.
Great find. Inspired by Spring (http://www.springframework.org/) in Java development, I implemented
Troy | Sunday, 12 November 2006 | 7:35 pmGreat find.
Inspired by Spring (http://www.springframework.org/) in Java development, I implemented an similar (using eval()) because it was easy, so the implementation is xml configrable, allowing debugging versions of the code, dropped in without recompiling.
One plus about your approach is eval() is not supported in Flash9, so your method is probably better.
I use the static reference links to setup a code library that is created by MTASC and pulled in via a skin file on the fly.
[...] http://dynamicflash.com/2005/03/class-finder/ [...]
Actionscript Classes » ClassFinder | Saturday, 16 December 2006 | 5:14 am[...] http://dynamicflash.com/2005/03/class-finder/ [...]
[...] Nota: En AS2, se puede hacer lo mismo así:
Crear Dinámicamente Instancias de Clase en AS3 | ¿y por qué no? | Saturday, 13 June 2009 | 12:15 am[...] Nota: En AS2, se puede hacer lo mismo así: [...]