I always wondered where I would end up using custom namespaces in ActionScript 3. Now that I’ve been using them I have found a few bugs and gotchas, tips and tricks, and now I generally understand namespaces better (or think I do).
(when reading this article it will help if you already have some familiarity with namespaces in Flash & Flex. To learn more about namespaces awesomeness, John Lindquist has an excellent video post that covers the concepts really well and goes into some advanced topics)
To start with I’d like to present a unique review of namespaces concepts (this isn’t pasted from the documentation, so it might be either 1-more helpful or 2-just plain wrong). There are reportedly 5 types of namespaces, but I’m going to say there are only 4 (this is the helpful/wrong portion).
It’s cool to note that private members are not restricted to object instances, just to class scope. This means that one instance of Box can access the private members of another instance of Box, as long as your code is written in the same package/class (the same .AS file more or less).
Protected members are NOT available to super classes. If an object tries to access its own protected members in a superclass (eg this["mySubProperty"]) you will have a runtime error. Only public (or custom) namespace allows this.
Internal members defined in com.xtyler.foo.bar are not available to classes in com.xtyler.foo, or com.xtyler.foo.bar.sub. Because of this restriction I’ve never seen much of a use for the internal namespace … until now (see further down)
The above namespaces are all very unique and are particular to the behavior they embody. The last type of namespace I’d like to call a “named” namespace. Both public and custom namespaces can be available from any other class as long as that class supports the name. When using custom namespaces the name is supported through use namespace my_custom_ns; The public namespace is automatic, as if every class had use namespace public at the top. So custom namespaces can be considered public to any class that wants to know about them. This is seen when you have two members of the same name in one class, you have to label the member explicitly when access it or you will get an error “1000: Ambiguous reference to member.”
public class Component { public var data:Object; cust_ns var data:CustomClass; public function Component() { public::data = {}; cust_ns::data = new CustomClass(); } |
And that brings me to why custom namespaces are nice. Why use a custom namespace when it doesn’t really restrict access, when it’s just another version of public? It’s all about the API baby! Keeping it clean and simple so when someone else uses your class they don’t get overloaded with methods and properties they’ll never use, or can’t use.
Ok, so now with all the different tips and tricks and bug workarounds (yes, if you can believe it, Flex & Flash have problems with namespaces)
Flex Builder seems to have a tough time admitting that custom namespaces are valuable members of society. You won’t ever get auto-complete for custom namespaces. When using the a custom namespace (especially flash_proxy for some reason), the automatic “Organize Imports” behavior zaps the import … and it runs ever time you code-complete, so you’ll find yourself constantly replacing the import. But add the use namespace flash_proxy; line above your class and you’ll enjoy many hours of organized imports. It’s best to always add this line of code, even if you’re not accessing the members, just defining them.
And another thing, where you add that line of code makes a big difference. This one was pretty frustrating: if your use namespace is inside the class definition, you get various bugs showing themselves through the ASC. Not at first mind you, but as soon as you try and override a custom namespace method, or access one of two members that have the same name but different namespaces, you’ll run into errors such as “Namespace was not found or is not a compile-time constant.” Place the use namespace just outside of your class, inside the package definition.
package com.xtyler.foo { import com.xtyler.foo.bar_ns; // here use namespace bar_ns; public class SpaceNamer extends EventDispatcher { // not here // ... |
It’s a strange work-around, but it’s a work-around! I could not override a custom namespace for some time until I found that nugget. (thank you to some anonymous tip out there in the comments of a random forum I can’t seem to find again)
internal below can be any namespace, including one of your own. This of course can be handled by a method or something else entirely, but it’s nice to be able to interact with the same property.
public function get commands():Array { return _commands; } internal function set commands(value:Array):void { // internal setting to your hearts desire } |
my_ns::someObj["prop"] … the compiler thinks you’re trying to target someObj in that namespace and throws an error. Insert your namespace inside evaluation for precise resolution.
myObj.my_ns::prop; // or history.internal::commands = []; |
var cmd:Array = history.public::commands // getter is public history.internal::commands = cmd; // setter is internal |
package com.xtyler { public namespace xtyler_ns = "http://xtyler.com"; } |
When you give the namespace a string it can be redefined elsewhere (even under a different name) with that same string … the string becomes the namespace, the the identifier is just a name. So the idea is that you can define an Internal copy of the same namespace in every package and have access to other packages via the custom namespace, but keep the namespace a secret still. It’s not real security, but here it is.
package com.xtyler.foo { internal namespace secret = "https://confidential.xtyler.com"; } package com.xtyler.bar { internal namespace secret = "https://confidential.xtyler.com"; } package com.xtyler.foo.sub { // can even be a different name inside the package, but can be accessed as a shared namespace between packages internal namespace bigSecret = "https://confidential.xtyler.com"; } |
<xt:MyComponent xmlns:xt="http://xt.xtyler.com/2009"> <xt:ChildComponent/> </xt:MyComponent> |
See John’s excellent video post“>video post on namespaces for an example of this last one plus a lot more, seriously.
Once understood namespaces are a great tool in crafting API’s and making your objects clean and usable for other developers. I hope if you’re working with namespaces in ActionScript 3 you will find these guidelines useful.
Quick note:
Adobe advises against “use namespace”. You should always stick to the “mx_internal::foo()” convention.
@see http://opensource.adobe.com/wiki/display/flexsdk/Coding+Conventions
Do this:
import mx.core.mx_internal;
// Later, in some method…
mx_internal::doSomething();
Not this:
import mx.core.mx_internal;
use namespace mx_internal;
// Later, in some method…
doSomething();
Thanks John, good to know. When used above the class (in the package) “use namespace” works fine and keeps your import from disappearing. However I still revert to explicit coding using “mx_internal::foo()” to keep ambiguities out. So I don’t really benefit from its intended use