0

I need to run code in a class declaration before its instanciation. This would be especially useful to automatically register classes in a factory. See:

// Main.as
public class Main extends Sprite 
{
    public function Main() : void
    {
        var o : Object = Factory.make(42);
    }
}

// Factory.as
public class Factory
{
    private static var _factory : Array = new Array();

    public static function registerClass(id : uint, c : Class) : void
    {
        _factory[id] = function () : Object { return new c(); };   
    }

    public static function make(id : uint) : Object
    {
        return _factory[id]();
    }
}

// Foo.as
public class Foo
{
    // Run this code before instanciating Foo!
    Factory.registerClass(CLASS_ID, Foo);

    public static const CLASS_ID : uint = 42;
}

AFAIK, the JIT machine for the ActionScript language won't let me do that since no reference to Foo is made in the Main method. The Foo class being generated, I can't (and don't want to) register the classes in Main: I'd like to register all the exported classes in a specific package (or library). Ideally, this would be done through package introspection, which doesn't exist in ActionScript 3.

Do you know any fix (or other solution) to my design issue?

Warren Seine
  • 2,311
  • 2
  • 25
  • 38
  • Since AS3 doesn't have package introspection as you noted, I guess you'd have to write your own logic. I'd suggest creating a `Factory.init()` static method that registers all the classes and calling it from the constructor of the `Main.as` But how would you go about linking the id numbers with classes? How would another custom class know that `Foo` is 42? – Amarghosh Mar 08 '10 at 11:44
  • `Factory` is supposed to be a "dynamic" factory design pattern: it doesn't know which classes it is able to instanciate. Defining an `init()` method is therefore not an option. Concerning the key/value system, I use my own hashing algorithm to compute a "unique" class ID during code generation. (I've edited the above code to reflect the remark.) – Warren Seine Mar 08 '10 at 13:56

2 Answers2

0

You can use compiler options to include class byte code in the resulting SWF or SWC. But you have to compile with MXMLC (or COMPC for SWCs).

Florian Salihovic
  • 3,921
  • 2
  • 19
  • 26
0

I'm not 100% sure sure if this is what you're after, but have you tried using a Static Initializer?

public class Foo
{
    // Static Initializer
    {
        Factory.registerClass(CLASS_ID, Foo);
    }

    public static const CLASS_ID : uint = 42;
}

http://life.neophi.com/danielr/2006/12/static_initializers_in_as3.html

JonnyReeves
  • 6,119
  • 2
  • 26
  • 28
  • Your solution needs to make a first reference to `Foo` in the `Main` class to load the class in the AVM and to run the static initializer. It doesn't solve the actual problem. In my case, the machine "thinks" I don't need the class since I make no direct use of it. I would like to force the AVM to load all the classes in a specific package (even if no object is created yet) so that the static initializer is run. Then you solution would be perfect. – Warren Seine Mar 10 '10 at 11:39