Namespaces may make poor function pointers, but you’d be wise to not write them off so quickly. It turns out that they have an altogether different usage that can help you blend the speed advantages of public fields with the encapsulation and information hiding of getters and setters. Read on to learn more about this lovely compromise.

In addition to the Namespace class, AS3 features a namespace keyword, which is the subject of today’s article. So, let’s see how to use this keyword to declare a new namespace for a fictitious library called FooLib:

package foolib
{
	public namespace foolibinternal;
}

There are a few things to notice about the above:

  • There is no class or interface definition in the file and there is no need for one. This is similar to declaring a package-level function. Here we have a package-level namespace.
  • The namespace does not need to be assigned a value.
  • The file should be named foolibinternal.as and placed in the foolib directory.

Now that we have created a new namespace, let’s use it!

package foolib.movement
{
	import foolib.foolibinternal;
 
	public class MoveDirections
	{
		foolibinternal static const MOVE_NONE:int = -1;
		foolibinternal static const MOVE_UP:int = 0;
		foolibinternal static const MOVE_DOWN:int = 1;
		foolibinternal static const MOVE_LEFT:int = 2;
		foolibinternal static const MOVE_RIGHT:int = 3;
	}
}

Here we have made a class with some static constants, essentially an enumeration. The purpose of the class is to define the movement directions for some entity that is controlled by other classes in FooLib. Let’s see how choosing the foolibinternal namespace is the superior choice in this case:

  • public: MoveDirections and its constants would become part of the API exposed to users of FooLib, needlessly adding to the complexity of the API by presenting a class that has no use outside of FooLib.
  • private: The enumeration would be completely inaccessible to any other class that wants to use it.
  • protected: Only subclasses could use the enumeration, which is a bizarre restriction.
  • internal: Only other classes in the foolib package could use MoveDirections, limiting how classes can be logically split into appropriate packages, even sub-packages.

In contrast to all of the default access specifiers above, our custom namespace provides access to all of the classes in FooLib, regardless of whether or not they have subclassed or what package they are in. How do they get this access? Easy! Let’s see an example:

package foolib.entities
{
	import foolib.foolibinternal;
	import foolib.movement.MoveDirections;
	public class Robot
	{
		private var moveDir:int;
		public function Robot()
		{
			use namespace foolibinternal;
			this.moveDir = MoveDirections.MOVE_NONE;
		}
	}
}

There are just two easy steps here:

  1. Import the namespace just like you would import a class.
  2. Add a use namespace X in any function where you want access to the namespace.

If you don’t want to do the second step, you can use the namespace directly with this funky syntax:

package foolib.entities
{
	import foolib.foolibinternal;
	public class Robot
	{
		private var moveDir:int;
		public function Robot()
		{
			this.moveDir = MoveDirections.foolibinternal::MOVE_NONE;
		}
	}
}

However, there is a big caveat to this direct approach: it compiles to a dynamic access of the foolibinternal namespace via a Namespace class. Here’s how it looks in bytecode: (annotated by me)

getlex MoveDirections // get the MoveDirections class
getlex foolibinternal // get the foolibinternal namespace
coerce Namespace // force it to be a Namespace object
getproperty MOVE_NONE // dynamically access the namespace's MOVE_NONE field

Compare this to the trivial bytecode when we use namspace foolibinternal:

getlex MoveDirections // get the MoveDirections class
getproperty foolibinternal::MOVE_NONE // statically access the class' MOVE_NONE field

So we’ve seen how to declare the namespace, declare fields with the namespace as an access specifier, and how to use those fields from other code. Given the huge performance penalty of using the Namespace class, let’s look at a performance test to ensure that we’re not incurring any of that penalty when we use namespace:

mynamespace.as
package
{
	public namespace mynamespace;
}
NamespacesTest.as
package
{
	import flash.display.Sprite;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.utils.getTimer;
 
	public class NamespacesTest extends Sprite
	{
		mynamespace var myna:int;
		public var publ:int;
		private var priv:int;
		protected var prot:int;
		internal var inte:int;
 
		private var logger:TextField;
		private function log(msg:*): void { logger.appendText(msg+"\n"); }
		private var e:Enum;
		public function NamespacesTest()
		{
			logger = new TextField();
			logger.autoSize = TextFieldAutoSize.LEFT;
			addChild(logger);
 
			log("Namespace,Time");
 
			testPublic();
			testPrivate();
			testProtected();
			testInternal();
			testMyNamespaceUse();
			testMyNamespaceDirect();
		}
 
		private function testPublic(): void
		{
			const REPS:int = 100000000;
			var beforeTime:int = getTimer();
			for (var i:int = 0; i < REPS; ++i)
			{
				publ;
			}
			var afterTime:int = getTimer();
			log("public," + (afterTime-beforeTime));
		}
 
		private function testPrivate(): void
		{
			const REPS:int = 100000000;
			var beforeTime:int = getTimer();
			for (var i:int = 0; i < REPS; ++i)
			{
				priv;
			}
			var afterTime:int = getTimer();
			log("private," + (afterTime-beforeTime));
		}
 
		private function testProtected(): void
		{
			const REPS:int = 100000000;
			var beforeTime:int = getTimer();
			for (var i:int = 0; i < REPS; ++i)
			{
				prot;
			}
			var afterTime:int = getTimer();
			log("protected," + (afterTime-beforeTime));
		}
 
		private function testInternal(): void
		{
			const REPS:int = 100000000;
			var beforeTime:int = getTimer();
			for (var i:int = 0; i < REPS; ++i)
			{
				inte;
			}
			var afterTime:int = getTimer();
			log("internal," + (afterTime-beforeTime));
		}
 
		private function testMyNamespaceUse(): void
		{
			use namespace mynamespace;
			const REPS:int = 100000000;
			var beforeTime:int = getTimer();
			for (var i:int = 0; i < REPS; ++i)
			{
				myna;
			}
			var afterTime:int = getTimer();
			log("mynamespace (use)," + (afterTime-beforeTime));
		}
 
		private function testMyNamespaceDirect(): void
		{
			const REPS:int = 100000000;
			var beforeTime:int = getTimer();
			for (var i:int = 0; i < REPS; ++i)
			{
				mynamespace::myna;
			}
			var afterTime:int = getTimer();
			log("mynamespace (direct)," + (afterTime-beforeTime));
		}
	}
}

I ran this performance test with the following environment:

  • Flex SDK (MXMLC) 4.1.0.16076, compiling in release mode (no debugging or verbose stack traces)
  • Release version of Flash Player 10.3.181.22
  • 2.4 Ghz Intel Core i5
  • Mac OS X 10.6.7

And got these results:

Namespace Time
public 218
private 236
protected 212
internal 216
mynamespace (use) 216
mynamespace (direct) 14419

Here are the same results in chart form:

Namespaces Performance Test Results

As you can see, there is basically no difference between any of the default access specifiers (public, private, protected, internal) or even the custom namespace when we access it via use namespace. When we directly access the namespace and the compiler does the access dynamically via a Namespace class behind the scenes, we incur a 66x performance penalty!

In conclusion, namespaces can be very useful. They allow you to essentially create a library-level access specifier with minimal extra requirements to access them and zero performance penalty as long as you don’t directly access them with the funky MoveDirections.foolibinternal::MOVE_NONE syntax. Know of any other good uses for namespaces? Post a comment below!