I need to define a custom namespace in AS3 a couple times a year at most, and nearly every time, I forget how to do it. The docs tell you to use the “namespace” keyword (which I remember), but not where or how to use it (which is what I forget), and google isn’t much help. I always wind up opening mx_internal.as in the Flex SDK as a reference.
With that in mind, here’s a complete guide to using namespaces in AS3. Note that it is about access namespaces, not XML namespaces. Hopefully it saves other devs a few minutes of searching.
What are custom namespaces?
Namespaces allow you to control the access to the members (properties and methods) of a class. You are probably familiar with native access modifiers like public, protected, internal, and private. Custom namespaces allow you to define your own access rules.
What can I use namespaces for?
While there are a range of uses for custom namespaces, three stand out to me as most common:
1. Documenting special conditions for member access. For example, in an evolving API, you may be required to expose methods that aren’t stable. You could place them in a custom namespace (ex. “transitional”), and document it to warn developers that these methods are subject to change. It’s sort of like a EULA for APIs.
2. Providing custom access domains. Namespaces cannot enforce custom access rules (only extend the native access modifiers), but they can provide a way to segregate an API for different user types. For example, you could provide a public API for a library for most users, and an extended API for plugin developers that uses a custom namespace (ex. “plugin”).
As another example of both #1 & 2, Adobe uses the mx_internal namespace to expose methods that need to be accessed widely within the Flex framework, but aren’t meant to be utilized publicly. They document that this namespace is unsupported and subject to change. It has the side benefit of providing hooks for advanced developers that require deep access to the framework and are willing to risk future compatibility problems.
3. Preventing name collisions. You can define members that have the same names in different namespaces. This is particularly handy for dynamic objects. ActionScript 3 uses this for the Proxy object, isolating it’s built in methods in the flash_proxy namespace, so that they are accessible externally, but don’t collide with any user defined methods.
Defining namespaces.
Defining namespaces is easy, just use the “namespace” keyword.
public namespace my_namespace_name; public namespace my_other_namespace = "uri"; |
You can create your namespace within any existing namespace, including the built in namespaces (public, private, et al), but you will usually just make it public.
The name can be whatever you want (except reserved words). The naming convention for namespaces is all-lowercase, with words separated by underscores.
The uri is optional, but helps prevent naming conflicts in the case that someone else uses the same namespace name. This should point to a relevant uri, which ideally hosts some brief information on the namespace (though this is unnecessary). For example, Adobe points to http://www.adobe.com/2006/flex/mx/internal for mx_internal, but doesn’t actually host any content there.
Where do you define namespaces?
You can define namespaces in two places – within a class, or in a separate file. I haven’t been able to come up with a real use case for the former, so we’ll focus on the latter. Simply create a new file with the same name as your namespace inside the appropriate package path, and define the namespace in a package declaration:
// in com/gskinner/utils/my_namespace.as package com.gskinner.utils { public namespace my_namespace = "http://gskinner.com/as/namespaces/utils/my_namespace"; } |
Using namespaces.
First, you need to import your namespace.
import com.gskinner.utils.my_namespace; |
You can now use your namespace in the same way as the built-in namespaces. So instead of specifying a var or function as public or protected, you use your namespace.
my_namespace var myProperty:Number=-1; |
To access class members within a namespace, you import the namespace, and then you use the whacky double-colon namespace syntax to access properties inside it.
import com.gskinner.utils.my_namespace; trace(myDemo.my_namespace::myProperty); // traces -1. |
You can also “use” a namespace, which opens it within the current scope (class or method), and provides access without the namespace qualifier. This approach requires less typing when accessing a number of members in a namespace, but it makes the code more ambiguous (are you accessing a public method, or one in the open namespace?).
import com.gskinner.utils.my_namespace; use namespace my_namespace; trace(myDemo.myProperty); // traces -1. |
Got anything to add? Let me know in the comments.
One thing I do thoroughly dislike about namespace implementation in ActionScript, is that they can’t be used in interfaces. I would like to be able to declare an interface under a namespace.
As for your post, shouldn’t the second snippet read:
import com.gskinner.utils.my_namespace;
use namespace my_namespace;
trace(myDemo.myProperty); // traces -1.
since you’ve already defined that you are using the namespace ?
I put together a video tutorial explaining namespaces in as3 a few months ago:
http://pv3d.org/2009/01/30/actionscript-3-namespaces/
Covers pretty much everything you need to know.
Whoops, copy/paste error. Thanks!
Agreed on namespaces for interfaces, though there are a lot of things that could be improved in interfaces.
A good place to “use” a namespace is before a class definition, you need to do that anyway if you want to override namespaced methods, but it also reduces the access time to namespaced properties and methods. If you don’t “use” a namespace, access times are on-par with static properties and methods. Ambiguous code is avoided simply by always prefixing namespaced properties and methods with the namespace (i.e. my_namespace::myProperty ).
Hope that makes sense 🙂
haha i was just thinking about this today thinking that i dont know much about namespaces i should study them more, hahaha!!
Finally I understand the namespaces. Thanks a lot.
I was wondering about the influence of namespaces on performance. Isn’t it a bit slow ?
@lab9
See the comment I posted. If you “use” namespaces (use namespace foo) they don’t make any difference to performance, if you don’t “use” them they will reduce performance.
Can namespaces be used to limit access, like having a model class with public get accessors but set accessors are available only to a controller class?
Namespaces can also be used as a state management strategy e.g. stateNamespace::statefulMethod();
I have an ‘experimental’ namespace for APIs that are under development and still being tested/refined.
e.g.
reader.experimental::enableMultitouch();
I also sometimes have a ‘dependency’ namespace for variables that are declared just to pull in another class into the SWF.
e.g.
dependency var sliderDependency:Slider = null;
The cool thing about namespaces is that they make the code self-documenting.
@John Lindquist:
Excellent video tutorial! It cleared up many open questions about this namespace-thing.
Defining and using your own namespaces can also be extremely helpful if you have to deal with SOAP web services. I made a couple of posts about it back in 2006.
http://www.benclinkinbeard.com/2006/07/dealing-with-default-namespaces-in-flex-2as3/
http://www.benclinkinbeard.com/2006/07/datagrid-labelfunction-and-namespaces/
Great post!
I never understood namespaces until now.
I sometimes use namespaces to implements a sort of “mini strategy pattern.” It’s also a use for declaring namespaces within a class. Consider the following code, which probably won’t get formatted correctly:
package {
import flash.display.*;
public class Test extends Sprite {
private var currentMode:Namespace;
private namespace a;
private namespace b;
public function Test() {
this.mode = “a”;
doSomething();
this.mode = “b”;
doSomething();
}
public function doSomething():void {
currentMode::_doSomething();
}
a function _doSomething():void {
trace(“A”);
}
b function _doSomething():void {
trace(“B”);
}
public function set mode(m:String):void {
switch (m) {
case “a”:
currentMode = a;
break;
case “b”:
currentMode = b;
break;
}
}
}
}
This starts to pay off when you have more than one method that needs to do different things depending on the “mode” (or strategy). You have your “which mode am I on?” logic in one place (set mode) and then each mode-dependent method simply utilizes the currentMode::someMethod() technique.
Not as fancy, robust, or strict as a proper strategy pattern with interfaces and strategy objects, but if you want to keep things sort of self-contained or have a small amount of strategies to consider, then I’ve found this useful.
Yeah, that code didn’t survive the incoming-comment-gauntlet. I’ve put it here, in case you don’t like the idea of copying, pasting, and reformatting:
http://dump.thekeppleeffect.com/NamespaceStrategy.as
Thank you Dru for the code with fixes.
Great post …
Just a thought about Namespaces : beware of performance issues : private/protected/public are handled a little bit differently (see tamarin code) than custom namespaces. Using namespaces has to be done carefully. (and correct me if I’m wrong, but namespaces are AS3 specific and won’t make it in ecmascript 4).
Also it (namespace) looks like a 2nd way to do polymorphism : might be handy in some case (like you described), but it’s always confusing to have 2 mechanisms to do the same thing
My 2 cents
Thomas
Did someone know how to get a custom namespace by reflection(flash.utils.describeType)?
@Dru Kepple: Looks pretty cool – but does not compile in FDT? It tells me “Could not resolve function” on currentMode::_doSomething(), while a::_doSomething() and b::_doSomething() work
[Embed( source=”../resources/images.xml”,mimeType=”application/octet-stream”)]
private static const cls_images : Class;
private static var ba_images : ByteArray = new cls_images();
public static var images : XML = new XML(ba_images.readUTFBytes(ba_images.length));
You can string an ’embed’ together with more code while declaring additional data. For instance, if you use a script to identify resources and auto-generate a ‘Resource.as’ file to wrap your Embedded stuff, you can make that ‘Binary’ content into something more useful, such as XML, String, etc. while it’s doing the rest of its unspeakably evil work.