Have you ever looked at the returned value of the function flash.utils.getQualifiedClassName() and wondered why it includes :: between the package and the class name? For example, if you pass in a MouseEvent instance, you'll get the string value "flash.events::MouseEvent". The first time I tried it, I expected to receive "flash.events.MouseEvent" with a . because that's how you reference a packaged class in an import statement. I always thought the difference was a little strange, but I just shrugged and went about my business. Today, though, my mind must have been feeling a little extra clever than ususal because it suddenly dawned on me: you use :: as an operator in ActionScript 3 to access a namespace.
With one simple test, it became unquestionably clear that packages in ActionScript 3 are really an abstraction built on top of namespaces. Try running the following code using the Flex SDK or the Flash authoring tool:
namespace flash_events = "flash.events"; trace( flash_events::MouseEvent ); //output: [class MouseEvent]
No import needed!
I imagine this has ECMAScript 4 roots. In general, many of the OOP features of AS3, like class and package syntax, are considered syntactic sugar. How can AS3 developers benefit from this knowledge? I have no idea, but it's one of those discoveries that whispers, "someday, you may need me".
Josh,
This is really cool. Thanks for sharing.
–Daniel
Very interesting discovery. I had noticed the ::, but like you hadn’t given it a second thought.
Great post. I use package and class lookup a lot when doing reflection in Flash. I really love creating classes defined from XML. As you pointed out there is really nothing “interesting” you can do with this knowledge but understanding the principles behind how things work is a critical part of being a good developer. Thanks for the info…
Yep – I was working with XML in Flex/AS3 just yesterday, taking contents from two XML objects and creating a third one, and noticed it added a namespace attribute automatically referencing the class that was building it:
I thought that was interesting. Not exactly useful on this project - it adds bloat to the file - wonder if there is a setting to turn that off, but not a big deal. Cool feature though. So because of this, I'm thinking yeah, it may indeed have E4X roots.
Nice article.
You can actually use those namespace references as _variables_ and selectively switch between sets of values.
(assuming you have a class named LanguageTable with variables in the right namespaces)
namespace current_language = “english”;
trace(LanguageTable.current_language::NoFileError); // “File not found!”
current_language = “german”;
trace(LanguageTable.current_language::NoFileError); // “Datei nicht gefunden!”
Essential ActionScript 3.0 goes into some detail on this. Definitely worth a read. Very cool stuff.
Interesting discovery, cool to declare class from an xml then.
Thx for sharing,
S.
How funny! I just made the same discovery about the change from “.” to “::” yesterday.
Unlike you, I was just distressed. It took me an hour to sort out why my app wasn’t working.
Great discovery, used this in my answer to a stackoverflow question.
Great post. I love the idea of assisting developers so they only seeing the methods via intellisense (of Flex Builder) for methods they need to see. I created a new demo to show that off. http://www.blog.rivello.org/?p=422
this goes even further:
even public, protected and private are just namespaces:
usage from outside of the class would look like this:
var myref:* = object.(private::_privateObjectProperty);
wich compiles fine but (fortunately) throws a Type-Error when running:
TypeError: Error #1123: Filter-Operator not supported for type [type of object].
hopefully there is no way to get around this limitation (espacially for private and protected). I saw code-examples that changed properties of Flex-Components this way where those properties lay in the mx_internal-namespace.
karfau
Yes, you’re right, karfau. public/protected/private/internal are all namespaces. I think your code should look like this:
Parentheses are used for E4X filtering, so they’re in no way usable here.
However, that won’t work. I’ve spent a lot of time trying to hack namespaces to see just what I can get away with. It’s not possible to access a private member outside it’s class. The
privatenamespace is specifically defined with a different value in each class (on the global object, which is also a different object for each class file). So class Apple’s private is not the same as class Orange’s private.In fact, it appears that the virtual machine has some extra protection. With the right function calls, you can trace the string representation of a particular class’ private namespace. However, if you try to define it in another class, it still won’t let you access something that’s private. Likewise, if you assign the private namespace to a variable and return it in a function call from the owning class to another class, it’s still useless for accessing the private members. This may be AS3 traits in action, or the separation of global objects in classes, or maybe defined by the language itself. Regardless, I’ve spent hours trying to hack
privatejust because it sounded like a fun blog post. That sort of exploration actually led to the package/namespace relationship I revealed here.Josh’s last post is not strictly true (that you cannot access private member variables outside of the defining class). If you are able to obtain the right Namespace object, you can create a QName, and subscript the object via that to access any arbitrary property. The key issue is obtaining the actual Namespace object for a given class, which may not be possible in direct literal code. However….
One trick you can use is to use the getMemberNames() top level function in the flash.sampler package to retrieve an object that can be used to iterate over all of the member variable names (private or not) in a given object [you must be in the debug player for this to work, and there are other conditions as well]. Iterating over the returned object with a “for each” loop yields a series of QName objects that can be used via the subscript notation to access the value of the corresponding property, and this includes private member variables.
James, flash.sampler doesn’t really count because it only works in the debug player. For the record, I was able to pass a private namespace object outside a class, but it only worked inside the class. I think I got a runtime error when I tried using it outside.
Josh, I think the statement that was made was that it was absolutely impossible to access private member variables outside of their defining class. I have provided a counter example showing it is doable; obviously there must be some limitations to it for helping to ensure the integrity of the application once its deployed. I have also described a means by which it can be accomplished. Did you try using my method to access the member variables outside at all?
James, I confirmed that the QName returned from flash.sampler.getMemberNames() can be used to access the value of a private variable. I am unable to construct my own QName, with the same uri and localName, that is able to do the same thing, even in the debug player and in the same running SWF. There’s some magic in the one returned from getMemberNames().
The meaning of my original statement was that you can’t access private members in a production environment. I’m sorry for the confusion.
Right — I have experienced the same thing (can’t synthesize the namespace or QName objects that getMemberNames returns). There is one line in the docs that hints that the “special” namespace that is used to get at the private and otherwise inaccessible member variables is not utterable. I’m using this technique right now to do some object reference graph traversals, so it’s highly beneficial in specific circumstances.