AS3 Reflection
Type discovery, better known as reflection, is rather odd in Flex. There is no type system to describe the types like sooo many languages offer (even PHP5 finally got it right). The closest that I know of is flash.utils.describeType which is quite weird as it returns XML. The DTD for the XML is ugly to me, but everyone has their opinions. A simple class like..
public final class EmployeeTitle extends BaseModel
{
public var id:Number = NaN;
public var title:String = '';
public function EmployeeTitle()
{
super();
}
public static function fromXML(xml:XML):EmployeeTitle
{
return null; /* we should do something important here */
}
}
turns into the following XML…
<type name="kmbs.model::EmployeeTitle" base="kmbs.model::BaseModel" isDynamic="false" isFinal="true" isStatic="false">
<extendsClass type="kmbs.model::BaseModel"/>
<extendsClass type="Object"/>
<variable name="id" type="Number"/>
<variable name="title" type="String"/>
<method name="assignXML" declaredBy="kmbs.model::BaseModel" returnType="void">
<parameter index="1" type="XML" optional="false"/>
</method>
<method name="toString" declaredBy="kmbs.model::BaseModel" returnType="String"/>
<method name="toXML" declaredBy="kmbs.model::BaseModel" returnType="XML"/>
</type>
As I was looking for a way to marshal the type to XML for pushing to the server it seems like this was the closest I was going to get. So I wrote some code and got the basics working no problem. A few days ago I realized that most of my models would be a bit more useful if they were [Bindable] and thus dispatched events about their changes (lets keep those interfaces up to date eh?). So I added what .NET calls attributes and Flex calls metadata tags.. [Bindable] to my class.
[Bindable]
public final class EmployeeTitle extends BaseModel
{
/* .... */
}
Once I did this however, none of my XML marshaling was working because apparently the type descriptor is now totally different.
<type name="kmbs.model::EmployeeTitle" base="kmbs.model::BaseModel" isDynamic="false" isFinal="true" isStatic="false">
<extendsClass type="kmbs.model::BaseModel"/>
<extendsClass type="Object"/>
<implementsInterface type="flash.events::IEventDispatcher"/>
<method name="addEventListener" declaredBy="kmbs.model::EmployeeTitle" returnType="void">
<parameter index="1" type="String" optional="false"/>
<parameter index="2" type="Function" optional="false"/>
<parameter index="3" type="Boolean" optional="true"/>
<parameter index="4" type="int" optional="true"/>
<parameter index="5" type="Boolean" optional="true"/>
</method>
<accessor name="id" access="readwrite" type="Number" declaredBy="kmbs.model::EmployeeTitle">
<metadata name="Bindable">
<arg key="event" value="propertyChange"/>
</metadata>
</accessor>
<method name="hasEventListener" declaredBy="kmbs.model::EmployeeTitle" returnType="Boolean">
<parameter index="1" type="String" optional="false"/>
</method>
<method name="dispatchEvent" declaredBy="kmbs.model::EmployeeTitle" returnType="Boolean">
<parameter index="1" type="flash.events::Event" optional="false"/>
</method>
<method name="willTrigger" declaredBy="kmbs.model::EmployeeTitle" returnType="Boolean">
<parameter index="1" type="String" optional="false"/>
</method>
<method name="removeEventListener" declaredBy="kmbs.model::EmployeeTitle" returnType="void">
<parameter index="1" type="String" optional="false"/>
<parameter index="2" type="Function" optional="false"/>
<parameter index="3" type="Boolean" optional="true"/>
</method>
<accessor name="title" access="readwrite" type="String" declaredBy="kmbs.model::EmployeeTitle">
<metadata name="Bindable">
<arg key="event" value="propertyChange"/>
</metadata>
</accessor>
<method name="assignXML" declaredBy="kmbs.model::BaseModel" returnType="void">
<parameter index="1" type="XML" optional="false"/>
</method>
<method name="toString" declaredBy="kmbs.model::BaseModel" returnType="String"/>
<method name="toXML" declaredBy="kmbs.model::BaseModel" returnType="XML"/>
</type>
As you can see all of the variable tags have been replaced by accessor tags. And methods have been added in order to perform the Event handling/dispatching, but apparently the class doesn’t extend something special. Instead the compiler seemingly injects raw methods, which bothers me for some reason.
As you can see I find Flex’s internals rather weird instead of smart, but as I said, everyone has their opinions.