Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

  • Private methods (non-static as well as static ones) and private static fields are declared in new scope, shared by all class members. Thus, they are visible for every method, but not from outside. Non-static private method calls have to be rewritten to run with the correct this.
  • Private non-static fields are renamed: they are post-fixed by $ plus the inheritance level of the declaring class, so that they cannot name-clash with fields of the same name, declared in a subclass or superclass.
  • Internal members are post-fixed by $ plus the full package name (with . replaced by _), so that they cannot name-clash with members of the same name, declared in a subclass or superclass residing in another package.

Static code execution

In ActionScript, a class may not only contain static members, but also static code. Static fields may also have initializers which are quite similar to static code.
Static code and static initializers are executed exactly once, let's call this "the class is initialized". A class is initialized right before code that references it is executed. Note that this has nothing to do with import directives, nor does a class trigger immediate initialization of all classes to which it has static dependencies.

No matter how class initialization is triggered, it is always executed as a whole:

  1. first, its superclass is initialized
  2. then, all static initializers are evaluated, in the order in which they appear in the source code
  3. last, all static code statements are executed, in the order in which they appear in the source code

This AS3 feature is quite tricky to simulate efficiently without relying on ES5 get/set properties (see below).

Any reference to another class that could not yet be initialized would have to be wrapped by a function that triggers initialization if necessary:

Code Block

OtherClass.something

would become

Code Block

ensureInitialized(OtherClass).something

where ensureInitialized would be a runtime function that checks whether the given class is initialized, if not, perform the initialization, and in any case return the initialized class.
The problem is that this adds a function call to almost all expressions referring to another class, since it is often not possible to determine at compile time that another class must already have been initialized. Only superclasses are guaranteed to have been initialized before code in the current class may run.

Relying on ES5 get/set properties, self-initializing classes can be implemented much more efficiently. A potentially uninitialized class would be accessed as a property of a wrapping object, which could be the package object, e.g. acme.Foo. The trick is that property Foo is first defined by a get function that performs the initialization, then replaces itself by a simple read-only property with a direct reference to the (now initialized) class.

Another approach is to implement the most important cases more efficiently by wrapping the constructor and all static methods in initializing functions that first initialize the class, then execute the original code. This is the approach currently used by Frank's runtime prototype.

Interfaces plus "as" and "is" operator

...