Archive for February, 2009

CS4 doesn’t like the combo of internal classes and interfaces in AS3

Just prior to the public release of CS4, I had to spend some time at work testing how our API would install into the new Flash IDE.  Aside from some MXP file funkiness (which I may cover later) I encountered some very strange compiler errors.  Specifically, the compiler complained about many classes that implemented interfaces:

1044: Interface method foo in namespace IFoo not implemented by class MyClass.

Now, I knew for a fact that all of the interfaces were implemented properly and all of the classes compiled properly in Flash CS3 (and Flex 2 & 3).  Nevertheless, we rechecked all the code over and over.

The startling realization was that all of the classes effected were Singletons!  The Singleton pattern I generally use is the one from the excellent “Advanced ActionScript 3 with Design Patterns” by Joey Lott, Danny Patterson.  The gist of the pattern is that it makes use of a second class declared inside the main class’ AS file.  Non-public classes are accessible only to the main class of the file, and not anywhere else in your package.  (You can see the relevant pages here.)

Here is some code to illustrate the setup in use:

First, the main class, which implements IFoo and uses the Singleton Pattern

package
{
    public class MyClass implements IFoo {
        /** Singleton object */
        static private var _instance:MyClass;

        /** The constructor will throw an error if you do not
                      pass a SingletonEnforcer instance */

        public function MyClass(s:SingletonEnforcer){   }
       
        /** Method to retrieve an instance. */
        public static function getInstance():MyClass
        {
            if (!_instance) _instance = new MyClass( new SingletonEnforcer() );
            return _instance
        }
 
        /** Function required by IFoo interface */
        public function foo():void {}
    }
}

/** The enforcer class cannot be accessed outside this .as file */
class SingletonEnforcer {}

 
And, here is the definition of IFoo:

package
{
    /** A simple interface */
    public interface IFoo {
        function foo():void
    }
}

Easy enough, right? The method foo() is obviously implemented in the class. But as it turns out, CS4’s compiler doesn’t agree.

Once we discovered that the combination of the interface and the Singleton pattern was to blame, we started looking at all of the Singletons in the API. By a stroke of luck, we found one that did NOT generate the compiler error. The difference in that class was that it implemented TWO interfaces!

Bizarre as it seems, adding a second interface to the scheme above fixes the issue, and CS4 compiles the code without further issue. We decided to add an empty ISingleton interface which was then used to correct the issue wherever it cropped up.

package
{
    public class MyClass implements IFoo, ISingleton {
        /** yadda yadda */
    }
}
package{
     /** Add an empty interface to fix the issue */
    public interface ISingleton {}
}

Many thanks to Tim O’Hare for his help in diagnosing and fixing the issue.

Feel free to download the source files referenced here.

UPDATE: There is an ActionScript compiler bug logged for this issue. It is marked as Closed and transferred to the main bugbase, so hopefully it will be addressed.

,

7 Comments