Welcome to the second part of this series on dynamic access. Last time we covered indexing arrays and vectors. This time we’ll talk about dynamic classes and plain objects. These are definitely something to watch out for when writing performance-critical code.

The Flash API has a few dynamic classes. Arrays and Vectors are perhaps the most unfortunate among these. Nearly as unfortunate are MovieClips. Consider these really common lines of code for dealing with a SWF built from a FLA:

function onFormLoaded(form:MovieClip): void
{
	// 2 dynamic accesses:
	//   form.okButton
	//   (form.okButton).addEventListener
	form.okButton.addEventListener(MouseEvent.CLICK, onClick);
 
	// 5 more:
	//   form.okButton (x2)
	//   (form.okButton).gotoAndStop
	//   (form.okButton).buttonMode
	form.okButton.gotoAndStop("disabled");
	form.okButton.buttonMode = false;
	form.okButton.alpha = 0.5;
}

The above is not likely to be performance-critical code, but consider how many areas of a Flash game might change the properties of MovieClips per frame. Suddenly it starts to look more attractive to not, for example, set the visible flag every frame but instead cache it and only set it if needed. Also, the above can be improved by caching the form.okButton access:

function onFormLoaded(form:MovieClip): void
{
	// 1 dynamic access:
	var okButton:MovieClip = form.okButton;
 
	// 1 dynamic access:
	//   okButton.addEventListener
	okButton.addEventListener(MouseEvent.CLICK, onClick);
 
	// 3 more:
	//   okButton.gotoAndStop
	//   okButton.buttonMode
	okButton.gotoAndStop("disabled");
	okButton.buttonMode = false;
	okButton.alpha = 0.5;
}

This brings seven accesses down to only five while making future use of okButton faster as well. This kind of access caching can save a lot of dynamic accesses and is easy to do. Next, consider the lowly plain object:

var fullScreen:Object = { x:0, y:0, width:stage.stageWidth, height:stage.stageHeight };

I often see AS3 programmers using plain objects when a regular class already exists. Since the regular class is usually not dynamic, access to the variable’s fields is much faster. In this case, the programmer should have simply used flash.geom.Rectangle:

var fullScreen:Rectangle = new Rectangle(0, 0, stage.stageWidth, stage.stageHeight);

This has the added benefit of access to all of Rectangle’s methods plus type safety and code completion. The former code is simply inexcusable. What if the user wanted to add extra fields, perhaps in an attempt to do caching? In this case, a sub-class should be used:

class MyRectangle extends Rectangle
{
	private var __area:Number;
	public function MyRectangle(x:Number, y:Number, width:Number, height:Number)
	{
		super(x, y, width, height);
		updateArea();
	}
 
	public function get area(): Number
	{
		return __area;
	}
 
	override public function set width(width:Number): void
	{
		super.width = width;
		updateArea();
	}
 
	override public function set height(height:Number): void
	{
		super.height = height;
		updateArea();
	}
 
	private function updateArea(): Number
	{
		__area = this.width * this.height;
	}
}

The above is coded for cleanliness rather than speed. Even so, using it will be quite a lot faster than repeatedly accessing the dynamic plain object in the first version. To further speed up the above, consider this version that inlines updateArea() and sacrifices data protection for the cached area value for the sake of eliminating the get area function call and a few calls to the get width and get height functions:

class MyRectangle extends Rectangle
{
	public var area:Number;
	public function MyRectangle(x:Number, y:Number, width:Number, height:Number)
	{
		super(x, y, width, height);
		this.area = width*height;
	}
 
	override public function set width(width:Number): void
	{
		super.width = width;
		this.area = width * this.height;
	}
 
	override public function set height(height:Number): void
	{
		super.height = height;
		this.area = this.width * height;
	}
}

This is a good chunk faster than even the first version of MyRectangle. It also allows for code completion and type safety. While you might not be interested in adding an area field, this should serve as an example of how you can add on to the lowly Rectangle without resorting to plain objects. The resulting code should be much faster and easier to work with.

Thus concludes the second part of this series. In the case of the dynamic classes in Flash such as MovieClip (and any other one marked as dynamic in the Flash 10 AS3 Docs, your only hope is to minimize access to the dynamic fields though techniques like the caching of okButton above. When it comes to using plain objects, you are the one creating the dynamic class. Here you have much more control. I would suggest to you that you nip the problem in the bud and simply not create the dynamic class in the first place.