ActionScript 3

AS3 Reflection crapyness :

Today I spent a whole morning to figure out that AS3 sucks.

Today I’ve been implementing a simple factory method which receives a Class object and some parameters to be passed to the concrete class instance, something with a signature like this:

static public function createInstance(c:Class, ... args):Object

BUT…the implementation of such a clear and simple method has been a bloody bath, because AS3 doesn’t support a really cool way to do really cool stuff like this 😀
I thought the implementation would be simply something like

static public function createInstance(c:Class, ... args):Object
{
return new c(args);
}

or any other easy way (python taught me to think simple :)) BUT…
“new c(args);” means my class constructor accepts one parameter typed as an Array, and I really don’t want my custom classes to have this defect of form nor my custom factory not to be able to instance classes written by someone else, so the solution “classes to be instanciated by the factory must accept an array as constructor parameter” is absolutely out.

Next approach, “reflect all properties instead of having parameters passed to the constructor”… not really a solution. Not always classes’ properties have the same nametypewhatever of constructor parameters. It’s a compromise that my factory can’t accept because I wouldn’t be able to create whatever class instance but only “some” class instance :. out.

Next approach, “use Function.apply to pass some parameters (array) to a function as they were single variables”..hey! that’s a good one! Let’s try it with some function

class MyClass{
public function myfunc(foo:String,bar:uint):void
{
trace(foo, bar);
}
}

class MyOtherClass{
public function callmyfunc(... args):void
{
var c:MyClass = new MyClass();
c.myfunc.apply(null,args);
}
}

HEY! IT WORKS! holy crap! AS3 rocks!…wait, let’s try it with a constructor function…

class MyClass{
public function MyClass(foo:String,bar:uint):void
{
trace(foo, bar);
}
}

class MyOtherClass{
public function callmyfunc(... args):void
{
var c:MyClass = new MyClass().apply(null,args);
}
}

…ok, it doesn’t work : and throws a runtime error :/ “Property apply not found on MyClass and there is no default value”…mmm
ok, maybe I have to reference the constructor function, but how can I do it!?
let’s try with “Class.prototype.constructor

class MyClass{
public function MyClass(foo:String,bar:uint):void
{
trace(foo, bar);
}
}

class MyOtherClass{
public function callmyfunc(... args):void
{
var c:Class = MyClass;
var f:Function = c.prototype.constructor;
}
}

…error… Class.prototype.constructor returns the type of the caller class (in this case MyClass)…
so…what can I do?

Discarded solutions:
“classes to be instanciated by the factory must accept an array as constructor parameter”

“reflect all properties instead of having parameters passed to the constructor”
“use Function.apply to pass some parameters (array) to a function as they were single variables”
here’s the solution: (drums) THE CRAPY ONE!
better known as “switch it all baby”….

static public function create(c:Class, ... args):Object {
			switch(args.length){
				case 0: return new c();
				case 1: return new c(args[0]);
				case 2: return new c(args[0],args[1]);
				case 3: return new c(args[0],args[1],args[2]);
				case 4: return new c(args[0],args[1],args[2],args[3]);
				case 5: return new c(args[0],args[1],args[2],args[3],args[4]);
				default: throw new Error("too many arguments");
			}
			return null;
		}

if you need to pass more than 5 arguments just add some lines to the factory and you’re done…

I was completely pissed off when I found this horrible lack in AS3, really, I was about for starting to cry, so I submitted a feature request on bugs.adobe… I think it’s really a MUST for a “respectable” language, if you find it as necessary as I think take a minute to vote this feature.
https://bugs.adobe.com/jira/browse/FP-3364

Advertisements

One thought on “AS3 Reflection crapyness :

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s