Wednesday, December 5, 2007

Nuances of ActionScript 3 Object Constructors

For Java developers learning ActionScript 3.0, one of the biggest differences between the two languages they will eventually run into is ActionScript's treatment of class constructors. Java developers are especially likely to run into these issues when trying to implement an enum facility in ActionScript (like we used to have to do in Java before Java 5's introduction of enum) or otherwise implement a Singleton design pattern.

Unlike Java, ActionScript 3.0 does not allow a class constructor to be declared as private or protected. Chapter 4 ("Object-Oriented Programming in ActionScript") of Programming ActionScript 3.0 states that constructors (or "constructor methods") can only be public and adds that the public keyword is not even required. There are several ActionScript solutions and/or "hacks" introduced by individuals on the web. These include Overloading Constructors with (rest)..., Design Pattern in AS3, ActionScript 3 Singleton Redux, and On the Lack of Private and Protected Constructors. The final listed entry, On the Lack of Private and Protected Constructors, explains why, at least for now, ActionScript does not allow for private or protected constructors.

While ActionScript does allow overriding of methods (in most cases using the ActionScript override keyword, but this is not necessary when extending Object methods such as toString()), it does not allow method overloading. This means that you can implement a method in an ActionScript class that overrides its parent class's method, but you cannot have multiple methods in the same class with the same name differentiated by differing parameters. This limitation is more general than simply constructors (because it applies to all methods), but I focus on the constructors in this blog entry. Fortunately, as documented in Overloading Constructors with ...(rest), you can use a function similar to Java's variable arguments (another Java 5 feature) to support differing ActionScript object instantiations. I don't like this approach as much as having multiple constructors that explicitly define the API for instantiating the class, but it is better than nothing.

When reading ActionScript or Flash class information in the Flex 2 Language Reference, you will sometimes see multiple constructor methods defined in the class documentation. This does not imply that multiple constructors exist for that particular class. Instead, it means that there is a single constructor that accepts multiple parameters as defined in the documentation. For example, there is a Note for the top-level ActionScript Namespace class that explains why it appears in the documentation that there are two constructors for this class when there is actually only one constructor that behaves differently based on the parameters provided to it. In the Namespace example, you can pass the constructor either a single untyped parameter (which will be interpreted as the URI) or two untyped parameters (with the first interpreted as the namespace prefix and the second interpreted as the URI).

Chapter 4 of the book Programming in ActionScript 3.0 (see link above) also explains some other interesting nuances of ActionScript class constructors. For example, while an object's parent's constructor can be called from the object's constructor with the super() call, this call will be implicitly implemented if not specified. However, if the child class wants to access parent properties via super., then a call to super() (the method) must be explicitly called first.

ActionScript shares much conceptually and even sometimes syntactically with Java, but ActionScript's treatment of constructors has several nuances that will be unfamiliar to Java developers.

No comments: