One of AS3’s strong suits is its ability to very easily use classes in a dynamic way. Every once in a while, this leads MXMLC to completely remove some of your classes from the output SWF and you then get some very strange behavior. Read on for some strategies for using dynamic classes without going insane.

Just what kinds of dynamic usage are there? Well, one of the most popular is flash.utils.getDefinitionByName. This function takes a fully-qualified class name (e.g. “com.jacksondunstan.MyClass”, not “MyClass”) and returns you its definition. What is a definition? It’s typed as an Object, but in actuality it seems to always be a Class. When the class can’t be found, a ReferenceError is thrown. If anyone knows of a case where it returns a non-Class value, please let me know in the comments. Here’s an example using getDefinitionByName:

function instantiateClass(className:String): Object
{
	try
	{
		return new (getDefinitionByName(className) as Class)();
	}
	catch (err:ReferenceError)
	{
		return null;
	}
}

The above example is just a simple convenience wrapper for getDefinitionByName but more complex cases crop up all the time, especially when instantiating based on input data like configuration XML or FlashVars.

The next way you can dynamically instantiate a class is by using an ApplicationDomain. Your main SWF has the root ApplicationDomain and you can choose to load other SWFs into so-called “child” application domains. It’s very common to load a SWF of assets—perhaps published from the Flash Authoring Tool—and then instantiate items out of its library/ApplicationDomain. Here’s an example function that does just that:

function getMovieClipInstance(library:ApplicationDomain, className:String): MovieClip
{
	if (!library.hasDefinition(className))
	{
		return null;
	}
	return new (library.getDefinition(className) as Class)();
}

Now that we’ve seen how we can dynamically access classes, let’s talk about how the problem occurs. You see, MXMLC strips out any class it doesn’t think you’re using to save SWF size. While its intentions are noble—who doesn’t like to save file size?—it severely conflicts with the dynamic usage of classes. After all, if we only access classes dynamically, we’ll no longer have any explicit references to them. MXMLC only sees strings in our code and, rightly, doesn’t try to read into how those strings are being used. Still, it will strip out the classes and suddenly we will be getting back a lot of null values from functions like the above two examples.

So how can we go about making sure that these classes are built into the SWF? I’ll show you two ways to do this, both only requiring minor source code changes.The first is to add some references to the classes in question as fields of any class in your source code:

class MyClass
{
	private static const ClassADependency:Class = ClassA;
	private static const ClassBDependency:Class = ClassB;
	private static const ClassCDependency:Class = ClassC;
	// ... more classes you depend on
}

The second approach is to reference the dependent classes in a no-op function with a scary name:

private static function CLASS_DEPENDENCIES_DO_NOT_CALL(): void
{
	ClassA;
	ClassB;
	ClassC;
	// ... more classes you depend on
}

Since you have any option, let’s compare them to see which is the better approach:

  Fields Function
Typing One line (easy copy/paste) + imports Just the class name + imports
Execution Speed Very small initialization at startup None (if not called)
Readability A few extra characters of clutter Simple list of class names
Maintainability Add/remove one line Add/remove one line
Accidental Usage Impossible, even by dynamic nulling Possible, but cheap and can’t crash

Personally, I prefer the function-based approach. Which way do you prefer? Do you know of any other good ways of getting around this problem? Feel free to add your own approach in the comments.