AS2 Lazy Construction Weirdness
Update: (See comments) I completely forgot that subclasses call the superclass constructor by default. Don't I feel dumb right now. But I'll leave this post here as an exercise in pointlessly using __resolve to decorate classes on-demand.
Consider this strange example. I have a class, called Widget. This class contains core code for handling all kinds of Widgets. Other people will be extending this class to create their own varieties of Widget (BendyWidget, SpinnyWidget).
Now, in my core class I want to add EventDispatcher functions, so I can dispatch certain core events like "exploded".
Cool, I'll just put the code in Widget's constructor function and everything is good, right?
Now what if my Widget constructor never gets called because I can't rely on the creators of BendyWidget to call super(); in their constructor function.. how can I guarantee that my class will have the event dispatcher functions?
Now I may be missing something really obvious but heres what I came up with: a way to force event dispatcher functions on my class (and all subclasses) at run-time with the Object.__resolve method.
Here is my Widget class:
class Widget
{
public var addEventListener:Function;
public var removeEventListener:Function;
public var dispatchEvent:Function;
public function Widget()
{
}
public function __resolve(fname)
{
trace("Resolving: "+fname);
switch (fname)
{
case "addEventListener":
case "removeEventListener":
case "dispatchEvent":
trace("Extending Widget with EventDispatcher methods");
mx.events.EventDispatcher.initialize(this);
return this[fname];
break;
default:
return undefined;
break;
}
}
public function dispatchMessage(str:String):Void
{
dispatchEvent({type: "message", message: str});
}
}
And here is an example control class:
class Control
{
public var myWidget:Widget;
public function Control()
{
myWidget = new Widget();
trace("Adding Event Listener");
myWidget.addEventListener("message", doMessage);
trace("Calling Widget.dispatchMessage");
myWidget.dispatchMessage("Hello");
}
public static function main()
{
return new Control();
}
private function doMessage(eventObject:Object):Void
{
trace(eventObject.message);
}
}
Now if we call Control.main() we get this output:
Adding Event Listener
Resolving: addEventListener
Extending Widget with EventDispatcher methods
Resolving: __q_message
Calling Widget.dispatchMessage
Resolving: messageHandler
Hello
So it works.
So.. I guess what I'm asking for is comments on this lazy construction method. Have I missed something really obvious?


June 14th, 2005 at 5:06 pm
you are not extending the 'Control' class from 'Widget'
using composition (as you did hereabove) always calls the constructor function, hence this always works, but it shouldn't work if you 'extend' Control from Widget
June 14th, 2005 at 5:11 pm
Hi cedric,
The Control class is just an example class to show things working, sorry for not being clear.
There would be other classes not shown here that extend Widget.
In the control class you can replace "myWidget = new Widget();" with "myWidget = new ExtendedWidget();"
June 14th, 2005 at 5:18 pm
I see ...
so if ExtendedWidget extends Widget and does not call 'super()' in its constructor, it will still initialize eventDispatcher ??
June 14th, 2005 at 5:20 pm
Yep, thats the goal!
June 14th, 2005 at 5:33 pm
I know it is ... but I was *just* doubting this would work with an 'ExtendedWidget' that doesn't calls super in its constructor ... your composition made me go south
thanks!
June 14th, 2005 at 6:43 pm
The compiler will add a call to super() in subclasses if omitted.
June 14th, 2005 at 7:03 pm
Haha.. thanks Robert, I knew I was missing something really basic.
Talk about over-thinking a problem..!
June 14th, 2005 at 7:14 pm
Robert takes the prize.