Home >
About Advanced Flash Tactics
Advanced Flash Tactics or AFTs are techniques that come from deep within the Flash Art Of War, the oldest Flash military treatise in the world. Each AFT is designed to be quickly digested, usually only taking a few minutes to get up and running, and contains valuable information you can directly apply to your next Flash campaign. In this AFT I will go over - describeType.
In AS3 we don't have a lot of options for doing Reflection. Incase you are not familiar with reflection here is a nifty little definition:
In computer science, reflection is the process by which a computer program can observe and modify its own structure and behavior. The programming paradigm driven by reflection is called reflective programming. - wikipedia
The little bit of reflection we can do is handled by the describeType function in the flash.utils package. In order to use describeType you will need to import its package and then call describeType and pass it any instance of a class. Here is a quick example:
import flash.text.TextField;
import flash.utils.describeType;
var classAsXML:XML = describeType(new TextField());
trace(classAsXML.toXMLString());
Outputs
<type name="flash.text::TextField" base="flash.display::InteractiveObject" isDynamic="false" isFinal="false" isStatic="false">
<metadata name="Event">
<arg key="name" value="textInput"/>
<arg key="type" value="flash.events.TextEvent"/>
</metadata>
<metadata name="Event">
<arg key="name" value="scroll"/>
<arg key="type" value="flash.events.Event"/>
</metadata>
<metadata name="Event">
<arg key="name" value="link"/>
<arg key="type" value="flash.events.TextEvent"/>
</metadata>
<metadata name="Event">
<arg key="name" value="change"/>
<arg key="type" value="flash.events.Event"/>
</metadata>
<extendsClass type="flash.display::InteractiveObject"/>
<extendsClass type="flash.display::DisplayObject"/>
<extendsClass type="flash.events::EventDispatcher"/>
<extendsClass type="Object"/>
<implementsInterface type="flash.display::IBitmapDrawable"/>
<implementsInterface type="flash.events::IEventDispatcher"/>
<method name="getRawText" declaredBy="flash.text::TextField" returnType="String">
<metadata name="Inspectable">
<arg key="environment" value="none"/>
</metadata>
</method>
<accessor name="autoSize" access="readwrite" type="String" declaredBy="flash.text::TextField"/>
<accessor name="defaultTextFormat" access="readwrite" type="flash.text::TextFormat" declaredBy="flash.text::TextField"/>
<method name="appendText" declaredBy="flash.text::TextField" returnType="void">
<parameter index="1" type="String" optional="false"/>
</method>
<method name="getImageReference" declaredBy="flash.text::TextField" returnType="flash.display::DisplayObject">
<parameter index="1" type="String" optional="false"/>
</method>
<accessor name="selectedText" access="readonly" type="String" declaredBy="flash.text::TextField">
<metadata name="Inspectable">
<arg key="environment" value="none"/>
</metadata>
</accessor>
<accessor name="textWidth" access="readonly" type="Number" declaredBy="flash.text::TextField"/>
<accessor name="htmlText" access="readwrite" type="String" declaredBy="flash.text::TextField"/>
<method name="getTextFormat" declaredBy="flash.text::TextField" returnType="flash.text::TextFormat">
<parameter index="1" type="int" optional="true"/>
<parameter index="2" type="int" optional="true"/>
</method>
<method name="getLineMetrics" declaredBy="flash.text::TextField" returnType="flash.text::TextLineMetrics">
<parameter index="1" type="int" optional="false"/>
</method>
<accessor name="scrollV" access="readwrite" type="int" declaredBy="flash.text::TextField"/>
<method name="getCharIndexAtPoint" declaredBy="flash.text::TextField" returnType="int">
<parameter index="1" type="Number" optional="false"/>
<parameter index="2" type="Number" optional="false"/>
</method>
<method name="getLineIndexAtPoint" declaredBy="flash.text::TextField" returnType="int">
<parameter index="1" type="Number" optional="false"/>
<parameter index="2" type="Number" optional="false"/>
</method>
<accessor name="bottomScrollV" access="readonly" type="int" declaredBy="flash.text::TextField"/>
<method name="getLineIndexOfChar" declaredBy="flash.text::TextField" returnType="int">
<parameter index="1" type="int" optional="false"/>
</method>
<accessor name="backgroundColor" access="readwrite" type="uint" declaredBy="flash.text::TextField"/>
<accessor name="embedFonts" access="readwrite" type="Boolean" declaredBy="flash.text::TextField"/>
<accessor name="text" access="readwrite" type="String" declaredBy="flash.text::TextField"/>
<accessor name="maxChars" access="readwrite" type="int" declaredBy="flash.text::TextField"/>
<method name="setTextFormat" declaredBy="flash.text::TextField" returnType="void">
<parameter index="1" type="flash.text::TextFormat" optional="false"/>
<parameter index="2" type="int" optional="true"/>
<parameter index="3" type="int" optional="true"/>
</method>
<method name="setSelection" declaredBy="flash.text::TextField" returnType="void">
<parameter index="1" type="int" optional="false"/>
<parameter index="2" type="int" optional="false"/>
</method>
<accessor name="border" access="readwrite" type="Boolean" declaredBy="flash.text::TextField"/>
<accessor name="background" access="readwrite" type="Boolean" declaredBy="flash.text::TextField"/>
<accessor name="selectionEndIndex" access="readonly" type="int" declaredBy="flash.text::TextField"/>
<accessor name="selectable" access="readwrite" type="Boolean" declaredBy="flash.text::TextField"/>
<accessor name="antiAliasType" access="readwrite" type="String" declaredBy="flash.text::TextField"/>
<method name="replaceText" declaredBy="flash.text::TextField" returnType="void">
<parameter index="1" type="int" optional="false"/>
<parameter index="2" type="int" optional="false"/>
<parameter index="3" type="String" optional="false"/>
</method>
<accessor name="alwaysShowSelection" access="readwrite" type="Boolean" declaredBy="flash.text::TextField"/>
<accessor name="maxScrollV" access="readonly" type="int" declaredBy="flash.text::TextField"/>
<accessor name="sharpness" access="readwrite" type="Number" declaredBy="flash.text::TextField"/>
<accessor name="thickness" access="readwrite" type="Number" declaredBy="flash.text::TextField"/>
<accessor name="displayAsPassword" access="readwrite" type="Boolean" declaredBy="flash.text::TextField"/>
<method name="getFirstCharInParagraph" declaredBy="flash.text::TextField" returnType="int">
<parameter index="1" type="int" optional="false"/>
</method>
<method name="getLineText" declaredBy="flash.text::TextField" returnType="String">
<parameter index="1" type="int" optional="false"/>
</method>
<accessor name="wordWrap" access="readwrite" type="Boolean" declaredBy="flash.text::TextField"/>
<accessor name="length" access="readonly" type="int" declaredBy="flash.text::TextField"/>
<accessor name="textHeight" access="readonly" type="Number" declaredBy="flash.text::TextField"/>
<accessor name="mouseWheelEnabled" access="readwrite" type="Boolean" declaredBy="flash.text::TextField"/>
<method name="getLineLength" declaredBy="flash.text::TextField" returnType="int">
<parameter index="1" type="int" optional="false"/>
</method>
<method name="insertXMLText" declaredBy="flash.text::TextField" returnType="void">
<parameter index="1" type="int" optional="false"/>
<parameter index="2" type="int" optional="false"/>
<parameter index="3" type="String" optional="false"/>
<parameter index="4" type="Boolean" optional="true"/>
<metadata name="Inspectable">
<arg key="environment" value="none"/>
</metadata>
</method>
<accessor name="restrict" access="readwrite" type="String" declaredBy="flash.text::TextField"/>
<accessor name="gridFitType" access="readwrite" type="String" declaredBy="flash.text::TextField"/>
<accessor name="caretIndex" access="readonly" type="int" declaredBy="flash.text::TextField"/>
<accessor name="borderColor" access="readwrite" type="uint" declaredBy="flash.text::TextField"/>
<method name="getCharBoundaries" declaredBy="flash.text::TextField" returnType="flash.geom::Rectangle">
<parameter index="1" type="int" optional="false"/>
</method>
<accessor name="condenseWhite" access="readwrite" type="Boolean" declaredBy="flash.text::TextField"/>
<accessor name="styleSheet" access="readwrite" type="flash.text::StyleSheet" declaredBy="flash.text::TextField"/>
<accessor name="numLines" access="readonly" type="int" declaredBy="flash.text::TextField"/>
<accessor name="type" access="readwrite" type="String" declaredBy="flash.text::TextField"/>
<accessor name="useRichTextClipboard" access="readwrite" type="Boolean" declaredBy="flash.text::TextField"/>
<method name="getParagraphLength" declaredBy="flash.text::TextField" returnType="int">
<parameter index="1" type="int" optional="false"/>
</method>
<accessor name="multiline" access="readwrite" type="Boolean" declaredBy="flash.text::TextField"/>
<accessor name="scrollH" access="readwrite" type="int" declaredBy="flash.text::TextField"/>
<accessor name="selectionBeginIndex" access="readonly" type="int" declaredBy="flash.text::TextField"/>
<method name="replaceSelectedText" declaredBy="flash.text::TextField" returnType="void">
<parameter index="1" type="String" optional="false"/>
</method>
<method name="getLineOffset" declaredBy="flash.text::TextField" returnType="int">
<parameter index="1" type="int" optional="false"/>
</method>
<accessor name="maxScrollH" access="readonly" type="int" declaredBy="flash.text::TextField"/>
<accessor name="textColor" access="readwrite" type="uint" declaredBy="flash.text::TextField"/>
<method name="getTextRuns" declaredBy="flash.text::TextField" returnType="Array">
<parameter index="1" type="int" optional="true"/>
<parameter index="2" type="int" optional="true"/>
<metadata name="Inspectable">
<arg key="environment" value="none"/>
</metadata>
</method>
<method name="getXMLText" declaredBy="flash.text::TextField" returnType="String">
<parameter index="1" type="int" optional="true"/>
<parameter index="2" type="int" optional="true"/>
<metadata name="Inspectable">
<arg key="environment" value="none"/>
</metadata>
</method>
<accessor name="doubleClickEnabled" access="readwrite" type="Boolean" declaredBy="flash.display::InteractiveObject"/>
<accessor name="contextMenu" access="readwrite" type="flash.ui::ContextMenu" declaredBy="flash.display::InteractiveObject"/>
<accessor name="tabEnabled" access="readwrite" type="Boolean" declaredBy="flash.display::InteractiveObject"/>
<accessor name="mouseEnabled" access="readwrite" type="Boolean" declaredBy="flash.display::InteractiveObject"/>
<accessor name="tabIndex" access="readwrite" type="int" declaredBy="flash.display::InteractiveObject"/>
<accessor name="accessibilityImplementation" access="readwrite" type="flash.accessibility::AccessibilityImplementation" declaredBy="flash.display::InteractiveObject">
<metadata name="Inspectable">
<arg key="environment" value="none"/>
</metadata>
</accessor>
<accessor name="focusRect" access="readwrite" type="Object" declaredBy="flash.display::InteractiveObject"/>
<accessor name="opaqueBackground" access="readwrite" type="Object" declaredBy="flash.display::DisplayObject"/>
<accessor name="cacheAsBitmap" access="readwrite" type="Boolean" declaredBy="flash.display::DisplayObject"/>
<accessor name="visible" access="readwrite" type="Boolean" declaredBy="flash.display::DisplayObject"/>
<accessor name="scaleX" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
<accessor name="parent" access="readonly" type="flash.display::DisplayObjectContainer" declaredBy="flash.display::DisplayObject"/>
<method name="hitTestPoint" declaredBy="flash.display::DisplayObject" returnType="Boolean">
<parameter index="1" type="Number" optional="false"/>
<parameter index="2" type="Number" optional="false"/>
<parameter index="3" type="Boolean" optional="true"/>
</method>
<accessor name="scaleY" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
<accessor name="mouseX" access="readonly" type="Number" declaredBy="flash.display::DisplayObject"/>
<accessor name="alpha" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
<accessor name="mouseY" access="readonly" type="Number" declaredBy="flash.display::DisplayObject"/>
<accessor name="width" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
<accessor name="mask" access="readwrite" type="flash.display::DisplayObject" declaredBy="flash.display::DisplayObject"/>
<method name="getRect" declaredBy="flash.display::DisplayObject" returnType="flash.geom::Rectangle">
<parameter index="1" type="flash.display::DisplayObject" optional="false"/>
</method>
<accessor name="rotation" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
<accessor name="x" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
<accessor name="transform" access="readwrite" type="flash.geom::Transform" declaredBy="flash.display::DisplayObject"/>
<method name="localToGlobal" declaredBy="flash.display::DisplayObject" returnType="flash.geom::Point">
<parameter index="1" type="flash.geom::Point" optional="false"/>
</method>
<method name="globalToLocal" declaredBy="flash.display::DisplayObject" returnType="flash.geom::Point">
<parameter index="1" type="flash.geom::Point" optional="false"/>
</method>
<accessor name="loaderInfo" access="readonly" type="flash.display::LoaderInfo" declaredBy="flash.display::DisplayObject"/>
<accessor name="blendMode" access="readwrite" type="String" declaredBy="flash.display::DisplayObject"/>
<accessor name="root" access="readonly" type="flash.display::DisplayObject" declaredBy="flash.display::DisplayObject"/>
<accessor name="filters" access="readwrite" type="Array" declaredBy="flash.display::DisplayObject"/>
<method name="hitTestObject" declaredBy="flash.display::DisplayObject" returnType="Boolean">
<parameter index="1" type="flash.display::DisplayObject" optional="false"/>
</method>
<accessor name="scale9Grid" access="readwrite" type="flash.geom::Rectangle" declaredBy="flash.display::DisplayObject"/>
<accessor name="y" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
<accessor name="stage" access="readonly" type="flash.display::Stage" declaredBy="flash.display::DisplayObject"/>
<accessor name="name" access="readwrite" type="String" declaredBy="flash.display::DisplayObject"/>
<accessor name="scrollRect" access="readwrite" type="flash.geom::Rectangle" declaredBy="flash.display::DisplayObject"/>
<accessor name="accessibilityProperties" access="readwrite" type="flash.accessibility::AccessibilityProperties" declaredBy="flash.display::DisplayObject"/>
<accessor name="height" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
<method name="getBounds" declaredBy="flash.display::DisplayObject" returnType="flash.geom::Rectangle">
<parameter index="1" type="flash.display::DisplayObject" optional="false"/>
</method>
<method name="dispatchEvent" declaredBy="flash.events::EventDispatcher" returnType="Boolean">
<parameter index="1" type="flash.events::Event" optional="false"/>
</method>
<method name="hasEventListener" declaredBy="flash.events::EventDispatcher" returnType="Boolean">
<parameter index="1" type="String" optional="false"/>
</method>
<method name="willTrigger" declaredBy="flash.events::EventDispatcher" returnType="Boolean">
<parameter index="1" type="String" optional="false"/>
</method>
<method name="toString" declaredBy="flash.events::EventDispatcher" returnType="String"/>
<method name="removeEventListener" declaredBy="flash.events::EventDispatcher" returnType="void">
<parameter index="1" type="String" optional="false"/>
<parameter index="2" type="Function" optional="false"/>
<parameter index="3" type="Boolean" optional="true"/>
</method>
<method name="addEventListener" declaredBy="flash.events::EventDispatcher" 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>
</type>
Lets talk about what this code did. As you can see I create a new variable that will store the xml that the describeType function returns. Next we create a new TextField instance in the describeType function. Once we have the output we can trace it and have a look at how TextField is described in XML. If you skim through the xml output you will see a very detailed skeleton of how the TextField class is put together. Lets focus on getting accessors (Getters and Setters) from the data:
Accessors (Getters/Setters)
var accessors:XMLList = classAsXML.accessor;
trace("accessors", accessors.length(), accessors);
output
accessors 71 <accessor name="restrict" access="readwrite" type="String" declaredBy="flash.text::TextField"/>
<accessor name="gridFitType" access="readwrite" type="String" declaredBy="flash.text::TextField"/>
<accessor name="caretIndex" access="readonly" type="int" declaredBy="flash.text::TextField"/>
<accessor name="borderColor" access="readwrite" type="uint" declaredBy="flash.text::TextField"/>
<accessor name="condenseWhite" access="readwrite" type="Boolean" declaredBy="flash.text::TextField"/>
<accessor name="styleSheet" access="readwrite" type="flash.text::StyleSheet" declaredBy="flash.text::TextField"/>
<accessor name="numLines" access="readonly" type="int" declaredBy="flash.text::TextField"/>
<accessor name="multiline" access="readwrite" type="Boolean" declaredBy="flash.text::TextField"/>
<accessor name="scrollH" access="readwrite" type="int" declaredBy="flash.text::TextField"/>
<accessor name="useRichTextClipboard" access="readwrite" type="Boolean" declaredBy="flash.text::TextField"/>
<accessor name="selectionBeginIndex" access="readonly" type="int" declaredBy="flash.text::TextField"/>
<accessor name="textColor" access="readwrite" type="uint" declaredBy="flash.text::TextField"/>
<accessor name="maxScrollH" access="readonly" type="int" declaredBy="flash.text::TextField"/>
<accessor name="autoSize" access="readwrite" type="String" declaredBy="flash.text::TextField"/>
<accessor name="defaultTextFormat" access="readwrite" type="flash.text::TextFormat" declaredBy="flash.text::TextField"/>
<accessor name="length" access="readonly" type="int" declaredBy="flash.text::TextField"/>
<accessor name="textWidth" access="readonly" type="Number" declaredBy="flash.text::TextField"/>
<accessor name="htmlText" access="readwrite" type="String" declaredBy="flash.text::TextField"/>
<accessor name="type" access="readwrite" type="String" declaredBy="flash.text::TextField"/>
<accessor name="scrollV" access="readwrite" type="int" declaredBy="flash.text::TextField"/>
<accessor name="selectionEndIndex" access="readonly" type="int" declaredBy="flash.text::TextField"/>
<accessor name="bottomScrollV" access="readonly" type="int" declaredBy="flash.text::TextField"/>
<accessor name="backgroundColor" access="readwrite" type="uint" declaredBy="flash.text::TextField"/>
<accessor name="selectedText" access="readonly" type="String" declaredBy="flash.text::TextField">
<metadata name="Inspectable">
<arg key="environment" value="none"/>
</metadata>
</accessor>
<accessor name="embedFonts" access="readwrite" type="Boolean" declaredBy="flash.text::TextField"/>
<accessor name="maxChars" access="readwrite" type="int" declaredBy="flash.text::TextField"/>
<accessor name="border" access="readwrite" type="Boolean" declaredBy="flash.text::TextField"/>
<accessor name="background" access="readwrite" type="Boolean" declaredBy="flash.text::TextField"/>
<accessor name="selectable" access="readwrite" type="Boolean" declaredBy="flash.text::TextField"/>
<accessor name="antiAliasType" access="readwrite" type="String" declaredBy="flash.text::TextField"/>
<accessor name="alwaysShowSelection" access="readwrite" type="Boolean" declaredBy="flash.text::TextField"/>
<accessor name="maxScrollV" access="readonly" type="int" declaredBy="flash.text::TextField"/>
<accessor name="sharpness" access="readwrite" type="Number" declaredBy="flash.text::TextField"/>
<accessor name="thickness" access="readwrite" type="Number" declaredBy="flash.text::TextField"/>
<accessor name="displayAsPassword" access="readwrite" type="Boolean" declaredBy="flash.text::TextField"/>
<accessor name="wordWrap" access="readwrite" type="Boolean" declaredBy="flash.text::TextField"/>
<accessor name="text" access="readwrite" type="String" declaredBy="flash.text::TextField"/>
<accessor name="textHeight" access="readonly" type="Number" declaredBy="flash.text::TextField"/>
<accessor name="mouseWheelEnabled" access="readwrite" type="Boolean" declaredBy="flash.text::TextField"/>
<accessor name="mouseEnabled" access="readwrite" type="Boolean" declaredBy="flash.display::InteractiveObject"/>
<accessor name="tabIndex" access="readwrite" type="int" declaredBy="flash.display::InteractiveObject"/>
<accessor name="accessibilityImplementation" access="readwrite" type="flash.accessibility::AccessibilityImplementation" declaredBy="flash.display::InteractiveObject">
<metadata name="Inspectable">
<arg key="environment" value="none"/>
</metadata>
</accessor>
<accessor name="focusRect" access="readwrite" type="Object" declaredBy="flash.display::InteractiveObject"/>
<accessor name="doubleClickEnabled" access="readwrite" type="Boolean" declaredBy="flash.display::InteractiveObject"/>
<accessor name="contextMenu" access="readwrite" type="flash.ui::ContextMenu" declaredBy="flash.display::InteractiveObject"/>
<accessor name="tabEnabled" access="readwrite" type="Boolean" declaredBy="flash.display::InteractiveObject"/>
<accessor name="scale9Grid" access="readwrite" type="flash.geom::Rectangle" declaredBy="flash.display::DisplayObject"/>
<accessor name="stage" access="readonly" type="flash.display::Stage" declaredBy="flash.display::DisplayObject"/>
<accessor name="accessibilityProperties" access="readwrite" type="flash.accessibility::AccessibilityProperties" declaredBy="flash.display::DisplayObject"/>
<accessor name="scrollRect" access="readwrite" type="flash.geom::Rectangle" declaredBy="flash.display::DisplayObject"/>
<accessor name="height" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
<accessor name="alpha" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
<accessor name="x" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
<accessor name="y" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
<accessor name="opaqueBackground" access="readwrite" type="Object" declaredBy="flash.display::DisplayObject"/>
<accessor name="cacheAsBitmap" access="readwrite" type="Boolean" declaredBy="flash.display::DisplayObject"/>
<accessor name="visible" access="readwrite" type="Boolean" declaredBy="flash.display::DisplayObject"/>
<accessor name="scaleX" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
<accessor name="mouseX" access="readonly" type="Number" declaredBy="flash.display::DisplayObject"/>
<accessor name="parent" access="readonly" type="flash.display::DisplayObjectContainer" declaredBy="flash.display::DisplayObject"/>
<accessor name="scaleY" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
<accessor name="mouseY" access="readonly" type="Number" declaredBy="flash.display::DisplayObject"/>
<accessor name="width" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
<accessor name="mask" access="readwrite" type="flash.display::DisplayObject" declaredBy="flash.display::DisplayObject"/>
<accessor name="rotation" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
<accessor name="name" access="readwrite" type="String" declaredBy="flash.display::DisplayObject"/>
<accessor name="transform" access="readwrite" type="flash.geom::Transform" declaredBy="flash.display::DisplayObject"/>
<accessor name="blendMode" access="readwrite" type="String" declaredBy="flash.display::DisplayObject"/>
<accessor name="root" access="readonly" type="flash.display::DisplayObject" declaredBy="flash.display::DisplayObject"/>
<accessor name="filters" access="readwrite" type="Array" declaredBy="flash.display::DisplayObject"/>
<accessor name="loaderInfo" access="readonly" type="flash.display::LoaderInfo" declaredBy="flash.display::DisplayObject"/>
Likewise we could look for properties by doing the following:
Properties
var variables:XMLList = classAsXML.variable;
trace("variables", variables.length(), variables);
Unfortunately you will not find any since the properties of the Textfield are all Getters and Setters. If you were to run this though your own class you would be able to see some. We don't have to stop there, as you may have noticed we can pull out all kinds of useful information:
Class Name
trace("ClassName", classAsXML.@name.split("::")[1]);
Output
ClassName TextField
Extended Classes
trace("Extends", classAsXML.extendsClass);
Output
<extendsClass type="flash.display::DisplayObject"/>
<extendsClass type="flash.events::EventDispatcher"/>
<extendsClass type="Object"/>
Implemented Interfaces
trace("Interfaces", classAsXML.implementsInterface);
Output
Interfaces <implementsInterface type="flash.display::IBitmapDrawable"/>
<implementsInterface type="flash.events::IEventDispatcher"/>
You may be questioning why you would ever need this information? Most of the time you can probably live without ever seeing it unless you are building a framework or need to access properties on a class without knowing them ahead of time. I actually use this in F*CSS to automatically convert Style properties (which are strings) to the correct type when I apply them to a class. You can see the source code for this here. Lets look at a simplified version of how this works:
In the following code I am going to make a lookup table with all the public properties of a class, along with the writable accessors and what each one's type is. Once I have this object I will be able to use it to look up the type of each property.
var list : XMLList = classAsXML.*;
var propMap : Object = new Object();
var item : XML;
for each (item in list) {
var itemName : String = item.name().toString();
switch(itemName) {
case "variable":
propMap[item.@name.toString()] = item.@type.toString();
break;
case "accessor":
var access : String = item.@access;
if((access == "readwrite") || (access == "writeonly")) {
propMap[item.@name.toString()] = item.@type.toString();
}
break;
}
}
// Output the contents of the propMap object
for (var prop:String in propMap)
{
trace(prop, "-", propMap[prop]);
}
Output
restrict - String
sharpness - Number
filters - Array
scale9Grid - flash.geom::Rectangle
mouseWheelEnabled - Boolean
focusRect - Object
styleSheet - flash.text::StyleSheet
blendMode - String
multiline - Boolean
borderColor - uint
gridFitType - String
height - Number
scrollRect - flash.geom::Rectangle
accessibilityImplementation - flash.accessibility::AccessibilityImplementation
tabEnabled - Boolean
condenseWhite - Boolean
alpha - Number
contextMenu - flash.ui::ContextMenu
y - Number
accessibilityProperties - flash.accessibility::AccessibilityProperties
useRichTextClipboard - Boolean
autoSize - String
textColor - uint
htmlText - String
tabIndex - int
defaultTextFormat - flash.text::TextFormat
x - Number
doubleClickEnabled - Boolean
scrollH - int
cacheAsBitmap - Boolean
opaqueBackground - Object
type - String
mouseEnabled - Boolean
scrollV - int
visible - Boolean
scaleY - Number
embedFonts - Boolean
maxChars - int
scaleX - Number
width - Number
border - Boolean
backgroundColor - uint
mask - flash.display::DisplayObject
rotation - Number
antiAliasType - String
thickness - Number
selectable - Boolean
name - String
background - Boolean
displayAsPassword - Boolean
wordWrap - Boolean
transform - flash.geom::Transform
text - String
alwaysShowSelection - Boolean
And there you have it, a complete list of each property on the TextField class along with the data type it requires. It will even show you the class name if the property is typed to a specific class. One last thing you can do with this type of reflection is Class validation. Lets say you have an array of instances that are not typed and you want to make sure each one you iterate through has a specific method before you attempt to call it, the describeType is what you need to use.
Using the describeType function is not as glamorous as say creating a 3d Engine or dynamically generating graphics but it is a key component in building a framework or toolkit. Hopefully this has cleared up what is possible with the returned XML and as always I would love to here how you have implemented this in your own project by leaving a comment below.





Facebook Application Development
Where possible (ie in flex apps) you really want to use mx.utils.DescribeTypeCache.describeType() as much will already be cached by the framework doing its thing and what isn't will be when you call it once. It is much faster.
Robert, good to know. I don't do a lot of Flex apps but in my FlashCamo & F*CSS frameworks I cache the PropertyMap class I create. Recursively calling describeType can be a huge bottleneck.
we've used this method to get a list of Constants that we can then use to query other Class methods and use for typeChecking at the same time. (useful for locale label management coming from xml)
[code]
public static function getConstantsList(clazz:Class):Array
{
var arr:Array = []
var describeTypeTest:DescribeTypeCacheRecord = DescribeTypeCache.describeType(clazz);
for each (var constant:XML in describeTypeTest.typeDescription..constant)
{
//Debug.log("ConstantsUtils: constant = " + constant.@name);
arr.push(clazz[constant.@name])
}
return arr;
}
[/code]
We have created an API on top of describeType that makes reflection much easier to work with. Check it out at http://www.as3commons.org/as3-commons-reflect/index.html
here's another reflection utility
http://blog.jactionscripters.com/2009/05/21/asreflect/
haven't actually used it but it looks a bit easier than parsing all that XML.
I'm in the early stages of using something like this for a general graphical layout/grid library. It can accept untyped parameters, the idea of this being that you can pass objects and the layout class decides how and whether the object(s) can be affected. The implementation is fairly similar to what you've got in F*CSS.
Im hoping to get this out into a google code project soon.
Hey Jesse, great article. Its good to see that that there are some reflection utilities out there as well.
This reminded me of a post I did way back when to force runtime checks for abstract method implementation in AS3.
http://www.as3dp.com/2007/05/05/runtime-checks-for-abstract-classes-and-methods-in-actionscript-30/
I just did it as an exercise and wouldn't recommend it for production code. As you mention, it takes a performance hit. I wasn't aware of the cached reflection info at the time - maybe that'll ease some of the bottlenecks.