Had a hell of a time debugging some OpenAMF calls yesterday. Turns out, when Flash deserializes your class, it basically takes a vanilla object, puts properties on it and assigns their values, and then points that instance’s __proto__ property to the prototype of the class you registered via Object.registerClass. The downside to this is it doesn’t run your setter functions on any getter/setters you have set on the class. Naturally, your getters fail immediately because they look to a private equivalent variable which is different, and when you call the setter… it’s really a function.
How Flash manages to keep “firstName” the public property and “firstName” the public getter function in the same namespace is beyond me, but regardless, I’ve tested in Flashcom last night, and the same thing happens there, too, so it appears to be how Flash deserializes your class.
The way we, “solved it” as my manager says, or “worked around it” as I claim, is emulating, EXACTLY the Java class equivalents. So, you have private properties in the Java model class, like:
private String firstName;
And same on the Flash side:
private var firstName:String;
And instead of getter/setter functions in Flash, you just use the get/set function methology:
public function getFirstName():String
{
return firstName;
}
public function setFirstName(val:String):Void
{
firstName = val;
}
I really don’t like this at all, and personally feel that there should either be an event letting you know when the class is deserialized (Flashcom does this for server-side ActionScript classes via the onInitialize event) so you can then run the getter/setters yourself, OR Flash should just intrinsically know there are getter/setters in place, and set the private variables accordingly. This gets sticky though because you’re now having the Flash Player run code on your classes. Thus, I vote for the first.
What is a Vanilla object?
Vanilla, like:
var o = {};
o.prop = ‘value’;
That’s an AS1 vanilla object. You could also do:
var o:Object = {};
or:
var o:Object = new Object();
Either way, if you trace it out:
trace(o.__proto__ == Object.prototype); // true
What I think Flash does when it’s deserializing your class from the AMF packets is taking this instance, and going:
o.__proto__ = YourClass.prototype;
Where YourClass is what you registered too up top in your code:
Object.registerClass(‘YourClass’, YourClass);
If Java sends a ‘YourClass’ class, then Flash then knows to map it to a YourClass, an ActionScript class.
I’ve seen this also in some of the AMFPHP example files. I think a decent workaround is creating an init method for that object, and running it immediately after you receive the object in the result event. This init method can transpose the variables to getters/setters.
It seems your constructor fires after all of your properties have their values set; I wasn’t seeing this in my Flashcom examples last night, but Brian Lesser from the Flashcom list sent me a working example. If it does work, I’ll see if there isn’t a way to set the privates during the constructor, thus having my getters work once the class is ready to be accessed. Stay tuned….
I’m only running into this issue now, so hadn’t seen this thread before, but…
Couldn’t you use the same ‘workaround’ that UIComponent uses for handling clip parameters? That would solve it (and, actually, I think it’s exactly the same problem).
I’ll have to give it a try and post my results…
agrees, but with this it can not be helped, it is in their blood