什么是反射
反射 (Reflection) 是指在程序在运行时 (run-time) 获取类信息的方式. 诸如实现动态创建类实例, 方法等. 在很语言中都有相关的的实现, 如 Java 和 c# 等
反射有什么用
在 as3 与 as2 不同, 类实例中任何元素, 如变量 (variable), 访问器 (accessor, 即 getter / setter), 方法 (method) 都是不可被 for..in 遍历的 (不是默认哦, 目前我还没找到办法可以让他被遍历),
并且不管你是否继承自 Object (默认继承就是 Object, 不写也一样), 是否把类声明为 dynamic.
或许有人会问自然是 Object 的子类, 不是可以用 setPropertyIsEnumerable 来设置是否隐藏变量么.
很遗憾的是经过的我的尝试, 在类里使用 setPropertyIsEnumerable("属性名") 编译器报告方法可能未定义.
随后尝试 super.setPropertyIsEnumerable("属性名"), 编译通过但抛运行时错误, 同样是方法未定义 -_-
而其他方法诸如 propertyIsEnumerable("属性名") 却可以正常使用
新建一个 ActionScript 项目, 分别创建下面 2 个类:
Dummy.as
package
{
public dynamic class Dummy extends Object
{
public var variable1:String;
public function Dummy () {
variable1 = "我是字符串";
// 使用下面 2 个句子分别会报告编译时错误和运行时错误
// setPropertyIsEnumerable("variable1");
// super.setPropertyIsEnumerable("accessorOfVar1");
}
public function get accessorOfVar1 ():String {
return "通过访问器访问, variable1 : " + variable1;
}
}
}
ReflectionSample.as
package {
import flash.display.Sprite;


public class ReflectionSample extends Sprite
{
public function ReflectionSample () {
testPropsEnumeration();
}
/**
* 测试 for..in 遍历
*
*/
private function testPropsEnumeration ():void {
trace("测试 for..in 循环, 遍历 Dummy 的实例");
var dummy:Dummy = new Dummy();
for (var i:String in dummy)
trace( i + " : " + dummy[i] );
}
}
}
最后测试 ReflectionSample, 记得用 debug 模式. 控制台中只会出现:
QUOTE:
------------------------------------------------------------
测试 for..in 循环, 遍历 Dummy 的实例
------------------------------------------------------------
显然 dummy 中的元素都没有被遍历出.
在 as1, 2 中很简单就可以实现的问题在 as3 得换个办法了, 谁让他们是传统的脚本语言呢.而在 as3 中, 就得通过反射来解决这个问题了. 方法会在文后介绍
动态创建实例
* 这部分内容帮助中已经有例子, 我摘要一些翻译一下, 不过我的 e 文很烂. 希望大家能看得懂.
as3 使用 flash.util.getDefinitionByName 动态获取类 (Class) 引用
帮助中该方法的描述 :
QUOTE:
------------------------------------------------------------
public function getDefinitionByName(name:String):Object
返回参数 name 中指定的类引用
参数 name:String - 类名称
返回 Object - 返回参数 name 中指定的类引用
错误 ReferenceError - 找不到参数 name 对应的公共定义
------------------------------------------------------------
使用方法如下:
获取类 flash.text.TextField 的引用. as 语句是无异常的类型转换. 如果转换失败那么目标变量将被设置成 null
var ClassReference:Class = getDefinitionByName("flash.text.TextField") as Class;
实例化所引用的类, 并设置一些属性
var instance:TextField = new ClassReference() as TextField;
instance.autoSize = "left";
instance.text = "我通过 getDefinitionByName 动态创建";
最后添加到场景中并显示
addChild(instance);
修改后的 ReflectionSample.as:
package
{
import flash.display.Sprite;
import flash.utils.getDefinitionByName;
import flash.text.TextField;

public class ReflectionSample extends Sprite
{
public function ReflectionSample () {
getDefinitionByNameSample();
}
/**
* 使用 flash.utils.getDefinitionByName 动态获取类 (Class) 并创建实例
*
*/
private function getDefinitionByNameSample ():void {
var ClassReference:Class = getDefinitionByName("flash.text.TextField") as Class;
var instance:TextField = new ClassReference() as TextField;
instance.autoSize = "left";
instance.text = "我通过 getDefinitionByName 动态创建";
addChild(instance);
}

}
}
动态获取类名称, 超类 (Superclass) 名称
有点像之前版本中的 typeof, 这个方法返回的是字符串
QUOTE:
------------------------------------------------------------
public function getQualifiedClassName(value:*):String
返回类的完全限定名 (fully qualified class name, qualified 我不知道怎么翻了..)
参数 value:* - 想要得到完全限定名的对象. 他可以是任何 ActionScript 类型, 对象实例, 简单类型如 uint 以及类类型.
返回 String - 包含类的完全限定名的字符串
------------------------------------------------------------
QUOTE:
------------------------------------------------------------
public function getQualifiedSuperclassName(value:*):String
返回目标对象基类的完全限定名,
本函数提供比 describeType 更简便的方法来获取基类的名称
提示: 本函数限制只寻找实例的继承层次,而 describeType() 函数使用的是类对象继承.
调用 describeType() 函数时返回的是基于超类以的类继承结构. 而 getQualifiedSuperclassName() 将忽略类的继承结构直接返回最接近的继承对象
例如, 理论上 String 类继承自 Class, 但调用 getQualifiedSuperclassName(String) 时返回的是 Object. 换句话说, 不管你传递的是类还是类的实例, 他们的返回值都是一样的
参数 value:* - 任何值.
返回 String - 基类的完全限定名, 如果没有的话返回 null
------------------------------------------------------------
例子:
实例化新的 Sprite, 然后获取他的类名并输出
var sprite1:Sprite = new Sprite();
var classNameOfSprite:String = getQualifiedClassName(Sprite);
trace("Sprite 的类名 : " + classNameOfSprite); // Sprite 的类名 : flash.display::Sprite
超类
var superclassNameOfSprite:String = getQualifiedSuperclassName(Sprite);
trace("Sprite 的超类 (基类) 类名 : " + superclassNameOfSprite); // Sprite 的超类 (基类) 类名 : flash.display::DisplayObjectContainer
根据刚刚获取的类名使用 创建实例
var SpriteClass:Class = getDefinitionByName(classNameOfSprite) as Class;
var sprite2:Sprite = new SpriteClass() as Sprite;
trace("sprite2 通过 getDefinitionByName 创建 Sprite 实例");
画一个 100 x 100 的矩形并显示
sprite2.graphics.beginFill(0xFF00FF);
sprite2.graphics.drawRect(0, 0, 100, 100);
sprite2.graphics.endFill();
addChild(sprite2);
修改后的 ReflectionSample.as
package {
import flash.display.Sprite;
import flash.utils.getDefinitionByName;
import flash.utils.getQualifiedClassName;
import flash.utils.getQualifiedSuperclassName;

public class ReflectionSample extends Sprite
{
public function ReflectionSample () {
getClassNameSample();
}
/**
* 使用 flash.utils.getQualifiedClassName 和 getQualifiedSuperclassName 获取类名称, 并动态创建该类
*
*/
private function getClassNameSample ():void {
var sprite1:Sprite = new Sprite();
var classNameOfSprite:String = getQualifiedClassName(Sprite);
trace("Sprite 的类名 : " + classNameOfSprite);
var superclassNameOfSprite:String = getQualifiedSuperclassName(Sprite);
trace("Sprite 的超类 (基类) 类名 : " + superclassNameOfSprite);
var SpriteClass:Class = getDefinitionByName(classNameOfSprite) as Class;
var sprite2:Sprite = new SpriteClass() as Sprite;
trace("sprite2 通过 getDefinitionByName 创建 Sprite 实例");
sprite2.graphics.beginFill(0xFF00FF);
sprite2.graphics.drawRect(0, 0, 100, 100);
sprite2.graphics.endFill();
addChild(sprite2);
}

}
}
获取类信息
QUOTE:
------------------------------------------------------------
public function describeType(value:*):XML
生成一个 XML 对象来描述参数中指定的 ActionScript 对象, 这个方法使 ActionScript 实现了反射编程的概念.
如果参数 value 是某类的实例, 那么返回的 XML 对象包含了此类中所有的实例属性, 但是不会包含任何的静态属性.
这种情况下你可以通过检查标签 <type> 中的 isStatic 属性来判断他, 当参数为某类的实例时, 这个值为 false.
要获取类的静态属性, 可以通过传递类本身到参数 value, 这样返回的 XML 对象不仅包括了类的静态属性, 也包括所有的实例属性.
实例属性被包含在 <factory> 标签中使它们和静态属性区别开来. 在这种情况下, <type> 标签的 isStatic 属性为 true.
提示: 如果你只需要获取对象的继承结构而不需要 describeType() 提供的其他信息, 可以使用 getQualifiedClassName() 和 getQualifiedSuperclassName() 来替代
下表描述了 describeType() 生成的 XML 的标签和属性 (按运行代码察看)
<!
DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"
>
<
html
>
<
head
>
<
meta
http-equiv
="Content-Type"
content
="text/html; charset=gb2312"
>
<
style
type
="text/css"
>
* { font- size : 1em; }
table, td, th { font-family : Verdana; border : 1px solid #000; border-collapse : collapse; background-color : #fefefe}
th { background-color : #ccc; }
</
style
>
</
head
>
<
body
>
<
table
width
="100%"
>
<
tr
><
th
>
标签
</
th
><
th
>
属性
</
th
><
th
>
说明
</
th
></
tr
>
<
tr
><
td
><
code
>
<
type
>
</
code
></
td
><
td
>
</
td
><
td
>
XML 对象的根标签
</
td
></
tr
>
<
tr
><
td
>
</
td
><
td
>
name
</
td
><
td
>
ActionScript 对象 (ActionScript object) 类型
</
td
></
tr
>
<
tr
><
td
>
</
td
><
td
>
base
</
td
><
td
>
当前对象的直属超类, 如果当前 ActionScript 对象是类对象, 那那么该值为
<
code
>
Class
</
code
>
.
</
td
></
tr
>
<
tr
><
td
>
</
td
><
td
>
isDynamic
</
td
><
td
>
如果当前 ActionScript 对象被定义为 dynamic, 那么该属性为
<
code
>
true
</
code
>
, 否则为
<
code
>
false
</
code
>
. 如果当前 ActionScript 对象是类对象, 那么该属性也为
<
code
>
true
</
code
>
, 因为 Class 类是 dynamic 的
</
td
></
tr
>
<
tr
><
td
>
</
td
><
td
>
isFinal
</
td
><
td
>
如果当前 ActionScript 对象被定义为 final, 那么该属性为
<
code
>
true
</
code
>
, 否则为
<
code
>
false
</
code
></
td
></
tr
>
<
tr
><
td
>
</
td
><
td
>
isStatic
</
td
><
td
>
如果当前 ActionScript 是类对象或者构造函数, 那么该属性为
<
code
>
true
</
code
>
, 否则为
<
code
>
false
</
code
>
. 该属性被命名为
<
code
>
isStatic
</
code
>
是因为如果值为
<
code
>
true
</
code
>
的话, 任何标签都不会被嵌套到
<
code
>
factory
</
code
>
标签中
</
td
></
tr
>
<
tr
><
td
><
code
>
<
extendsClass
>
</
code
></
td
><
td
>
</
td
><
td
>
使用
<
code
>
extendsClass
</
code
>
标签分别存放当前 ActionScript 对象的超类
</
td
></
tr
>
<
tr
><
td
>
</
td
><
td
>
type
</
td
><
td
>
当前 ActionScript 对象所继承的超类的名字
</
td
></
tr
>
<
tr
><
td
><
code
>
<
implementsInterface
>
</
code
></
td
><
td
>
</
td
><
td
>
使用
<
code
>
implementsInterface
</
code
>
标签分别存放当前 ActionScript 对象, 以及他的超类所实现的接口
</
td
></
tr
>
<
tr
><
td
>
</
td
><
td
>
type
</
td
><
td
>
当前 ActionScript 所实现的接口的名字
</
td
></
tr
>
<
tr
><
td
><
code
>
<
accessor
>
</
code
></
td
><
td
>
</
td
><
td
>
访问器是由 getter 和 setter 所定义的属性
</
td
></
tr
>
<
tr
><
td
>
</
td
><
td
>
name
</
td
><
td
>
该访问器的名字
</
td
></
tr
>
<
tr
><
td
>
</
td
><
td
>
access
</
td
><
td
>
该访问器的访问权限. 可能的值有
<
code
>
readonly
</
code
>
,
<
code
>
writeonly
</
code
>
, 和
<
code
>
readwrite
</
code
>
.
</
td
></
tr
>
<
tr
><
td
>
</
td
><
td
>
type
</
td
><
td
>
该属性的数据类型
</
td
></
tr
>
<
tr
><
td
>
</
td
><
td
>
declaredBy
</
td
><
td
>
指示由哪个类定义了该访问器
</
td
></
tr
>
<
tr
><
td
><
code
>
<
constant
>
</
code
></
td
><
td
>
</
td
><
td
>
常量是由
<
code
>
const
</
code
>
所定义的属性
</
td
></
tr
>
<
tr
><
td
>
</
td
><
td
>
name
</
td
><
td
>
该常量的名称
</
td
></
tr
>
<
tr
><
td
>
</
td
><
td
>
type
</
td
><
td
>
该常量的数据类型
</
td
></
tr
>
<
tr
><
td
><
code
>
<
method
>
</
code
></
td
><
td
>
</
td
><
td
>
方法是由类定义的一部分公开的函数
</
td
></
tr
>
<
tr
><
td
>
</
td
><
td
>
name
</
td
><
td
>
方法名
</
td
></
tr
>
<
tr
><
td
>
</
td
><
td
>
declaredBy
</
td
><
td
>
指示该方法由哪个类定义
</
td
></
tr
>
<
tr
><
td
>
</
td
><
td
>
returnType
</
td
><
td
>
方法的返回类型
</
td
></
tr
>
<
tr
><
td
><
code
>
<
parameter
>
</
code
></
td
><
td
>
</
td
><
td
>
使用
<
code
>
parameter
</
code
>
分别存放该方法的参数, 该标签被嵌套在
<
code
>
<
method
>
</
code
>
中
</
td
></
tr
>
<
tr
><
td
>
</
td
><
td
>
index
</
td
><
td
>
一个数字指示当前参数被传递时所在函数中的位置, 如果是首个参数, 那么该值为 1
</
td
></
tr
>
<
tr
><
td
>
</
td
><
td
>
type
</
td
><
td
>
该参数的类型
</
td
></
tr
>
<
tr
><
td
>
</
td
><
td
>
optional
</
td
><
td
>
如果该参数为可选的话为
<
code
>
true
</
code
>
, 否则为
<
code
>
false
</
code
></
td
></
tr
>
<
tr
><
td
><
code
>
<
variable
>
</
code
></
td
><
td
>
</
td
><
td
>
变量 (variable) 是由 var 语句所定义的变量
</
td
></
tr
>
<
tr
><
td
>
</
td
><
td
>
name
</
td
><
td
>
变量名
</
td
></
tr
>
<
tr
><
td
>
</
td
><
td
>
type
</
td
><
td
>
变量类型
</
td
></
tr
>
<
tr
><
td
><
code
>
<
factory
>
</
code
></
td
><
td
>
</
td
><
td
>
如果当前 ActionScript 对象是类对象或者构造函数, 所有的实例属性将会被嵌套进该标签. 如果
<
code
>
<
type
>
</
code
>
标签的
<
code
>
isStatic
</
code
>
属性为
<
code
>
true
</
code
>
, 所有属性 (properties) 和方法 (method) 将不会被嵌套进改标签中. 该标签只出现在当前 ActionScript 对象是类对象或者构造函数的情况下
</
td
></
tr
>
</
table
>
</
body
>
</
html
>
另外, 由 describeType() 返回的类描述信息中只会含有所有可被访问的元素, 即所有非定义为 private 的元素.
解释了这么多, 我们来看看返回的 XML 格式
flash 的内置类 flash.display.Sprite :
trace(describeType(Sprite);
返回:
<
type
name
="flash.display::Sprite"
base
="Class"
isDynamic
="true"
isFinal
="true"
isStatic
="true"
>
<
extendsClass
type
="Class"
/>
<
extendsClass
type
="Object"
/>
<
accessor
name
="prototype"
access
="readonly"
type
="*"
declaredBy
="Class"
/>
<
factory
type
="flash.display::Sprite"
>
<
extendsClass
type
="flash.display::DisplayObjectContainer"
/>
<
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"
/>
<
accessor
name
="hitArea"
access
="readwrite"
type
="flash.display::Sprite"
declaredBy
="flash.display::Sprite"
/>
<
method
name
="startDrag"
declaredBy
="flash.display::Sprite"
returnType
="void"
>
<
parameter
index
="1"
type
="Boolean"
optional
="true"
/>
<
parameter
index
="2"
type
="flash.geom::Rectangle"
optional
="true"
/>
</
method
>
<
accessor
name
="buttonMode"
access
="readwrite"
type
="Boolean"
declaredBy
="flash.display::Sprite"
/>
<
accessor
name
="graphics"
access
="readonly"
type
="flash.display::Graphics"
declaredBy
="flash.display::Sprite"
/>
<
accessor
name
="soundTransform"
access
="readwrite"
type
="flash.media::SoundTransform"
declaredBy
="flash.display::Sprite"
/>
<
method
name
="stopDrag"
declaredBy
="flash.display::Sprite"
returnType
="void"
/>
<
accessor
name
="dropTarget"
access
="readonly"
type
="flash.display::DisplayObject"
declaredBy
="flash.display::Sprite"
/>
<
accessor
name
="useHandCursor"
access
="readwrite"
type
="Boolean"
declaredBy
="flash.display::Sprite"
/>
<
method
name
="getChildAt"
declaredBy
="flash.display::DisplayObjectContainer"
returnType
="flash.display::DisplayObject"
>
<
parameter
index
="1"
type
="int"
optional
="false"
/>
</
method
>
<
method
name
="addChild"
declaredBy
="flash.display::DisplayObjectContainer"
returnType
="flash.display::DisplayObject"
>
<
parameter
index
="1"
type
="flash.display::DisplayObject"
optional
="false"
/>
</
method
>
<
method
name
="swapChildren"
declaredBy
="flash.display::DisplayObjectContainer"
returnType
="void"
>
<
parameter
index
="1"
type
="flash.display::DisplayObject"
optional
="false"
/>
<
parameter
index
="2"
type
="flash.display::DisplayObject"
optional
="false"
/>
</
method
>
<
method
name
="getChildByName"
declaredBy
="flash.display::DisplayObjectContainer"
returnType
="flash.display::DisplayObject"
>
<
parameter
index
="1"
type
="String"
optional
="false"
/>
</
method
>
<
method
name
="getObjectsUnderPoint"
declaredBy
="flash.display::DisplayObjectContainer"
returnType
="Array"
>
<
parameter
index
="1"
type
="flash.geom::Point"
optional
="false"
/>
</
method
>
<
accessor
name
="textSnapshot"
access
="readonly"
type
="flash.text::TextSnapshot"
declaredBy
="flash.display::DisplayObjectContainer"
/>
<
method
name
="removeChildAt"
declaredBy
="flash.display::DisplayObjectContainer"
returnType
="flash.display::DisplayObject"
>
<
parameter
index
="1"
type
="int"
optional
="false"
/>
</
method
>
<
method
name
="getChildIndex"
declaredBy
="flash.display::DisplayObjectContainer"
returnType
="int"
>
<
parameter
index
="1"
type
="flash.display::DisplayObject"
optional
="false"
/>
</
method
>
<
method
name
="areInaccessibleObjectsUnderPoint"
declaredBy
="flash.display::DisplayObjectContainer"
returnType
="Boolean"
>
<
parameter
index
="1"
type
="flash.geom::Point"
optional
="false"
/>
</
method
>
<
accessor
name
="mouseChildren"
access
="readwrite"
type
="Boolean"
declaredBy
="flash.display::DisplayObjectContainer"
/>
<
method
name
="removeChild"
declaredBy
="flash.display::DisplayObjectContainer"
returnType
="flash.display::DisplayObject"
>
<
parameter
index
="1"
type
="flash.display::DisplayObject"
optional
="false"
/>
</
method
>
<
method
name
="setChildIndex"
declaredBy
="flash.display::DisplayObjectContainer"
returnType
="void"
>
<
parameter
index
="1"
type
="flash.display::DisplayObject"
optional
="false"
/>
<
parameter
index
="2"
type
="int"
optional
="false"
/>
</
method
>
<
method
name
="contains"
declaredBy
="flash.display::DisplayObjectContainer"
returnType
="Boolean"
>
<
parameter
index
="1"
type
="flash.display::DisplayObject"
optional
="false"
/>
</
method
>
<
method
name
="addChildAt"
declaredBy
="flash.display::DisplayObjectContainer"
returnType
="flash.display::DisplayObject"
>
<
parameter
index
="1"
type
="flash.display::DisplayObject"
optional
="false"
/>
<
parameter
index
="2"
type
="int"
optional
="false"
/>
</
method
>
<
accessor
name
="numChildren"
access
="readonly"
type
="int"
declaredBy
="flash.display::DisplayObjectContainer"
/>
<
method
name
="swapChildrenAt"
declaredBy
="flash.display::DisplayObjectContainer"
returnType
="void"
>
<
parameter
index
="1"
type
="int"
optional
="false"
/>
<
parameter
index
="2"
type
="int"
optional
="false"
/>
</
method
>
<
accessor
name
="tabChildren"
access
="readwrite"
type
="Boolean"
declaredBy
="flash.display::DisplayObjectContainer"
/>
<
accessor
name
="tabEnabled"
access
="readwrite"
type
="Boolean"
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
="accessibilityImplementation"
access
="readwrite"
type
="flash.accessibility::AccessibilityImplementation"
declaredBy
="flash.display::InteractiveObject"
>
<
metadata
name
="Inspectable"
>
<
arg
key
="environment"
value
="none"
/>
</
metadata
>
</
accessor
>
<
accessor
name
="mouseEnabled"
access
="readwrite"
type
="Boolean"
declaredBy
="flash.display::InteractiveObject"
/>
<
accessor
name
="focusRect"
access
="readwrite"
type
="Object"
declaredBy
="flash.display::InteractiveObject"
/>
<
accessor
name
="tabIndex"
access
="readwrite"
type
="int"
declaredBy
="flash.display::InteractiveObject"
/>
<
accessor
name
="mask"
access
="readwrite"
type
="flash.display::DisplayObject"
declaredBy
="flash.display::DisplayObject"
/>
<
accessor
name
="scaleX"
access
="readwrite"
type
="Number"
declaredBy
="flash.display::DisplayObject"
/>
<
accessor
name
="scaleY"
access
="readwrite"
type
="Number"
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
="mouseY"
access
="readonly"
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
="name"
access
="readwrite"
type
="String"
declaredBy
="flash.display::DisplayObject"
/>
<
accessor
name
="y"
access
="readwrite"
type
="Number"
declaredBy
="flash.display::DisplayObject"
/>
<
accessor
name
="root"
access
="readonly"
type
="flash.display::DisplayObject"
declaredBy
="flash.display::DisplayObject"
/>
<
accessor
name
="width"
access
="readwrite"
type
="Number"
declaredBy
="flash.display::DisplayObject"
/>
<
accessor
name
="stage"
access
="readonly"
type
="flash.display::Stage"
declaredBy
="flash.display::DisplayObject"
/>
<
accessor
name
="loaderInfo"
access
="readonly"
type
="flash.display::LoaderInfo"
declaredBy
="flash.display::DisplayObject"
/>
<
accessor
name
="transform"
access
="readwrite"
type
="flash.geom::Transform"
declaredBy
="flash.display::DisplayObject"
/>
<
accessor
name
="height"
access
="readwrite"
type
="Number"
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
>
<
accessor
name
="filters"
access
="readwrite"
type
="Array"
declaredBy
="flash.display::DisplayObject"
/>
<
accessor
name
="blendMode"
access
="readwrite"
type
="String"
declaredBy
="flash.display::DisplayObject"
/>
<
accessor
name
="rotation"
access
="readwrite"
type
="Number"
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
="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
="cacheAsBitmap"
access
="readwrite"
type
="Boolean"
declaredBy
="flash.display::DisplayObject"
/>
<
method
name
="globalToLocal"
declaredBy
="flash.display::DisplayObject"
returnType
="flash.geom::Point"
>
<
parameter
index
="1"
type
="flash.geom::Point"
optional
="false"
/>
</
method
>
<
method
name
="getBounds"
declaredBy
="flash.display::DisplayObject"
returnType
="flash.geom::Rectangle"
>
<
parameter
index
="1"
type
="flash.display::DisplayObject"
optional
="false"
/>
</
method
>
<
accessor
name
="opaqueBackground"
access
="readwrite"
type
="Object"
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
="visible"
access
="readwrite"
type
="Boolean"
declaredBy
="flash.display::DisplayObject"
/>
<
accessor
name
="mouseX"
access
="readonly"
type
="Number"
declaredBy
="flash.display::DisplayObject"
/>
<
method
name
="willTrigger"
declaredBy
="flash.events::EventDispatcher"
returnType
="Boolean"
>
<
parameter
index
="1"
type
="String"
optional
="false"
/>
</
method
>
<
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
="toString"
declaredBy
="flash.events::EventDispatcher"
returnType
="String"
/>
<
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
>
<
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
>
</
factory
>
</
type
>
真是又臭又长啊. :o, 根据帮助中的描述, 所有的实例属性都被嵌套在了 <factory> 标签里.
我们再试一下获取实例的信息 :
var sprite1:Sprite = new Sprite();
var instanceInfo:XML = describeType(sprite1);
返回 :
<
type
name
="flash.display::Sprite"
base
="flash.display::DisplayObjectContainer"
isDynamic
="false"
isFinal
="false"
isStatic
="false"
>
<
extendsClass
type
="flash.display::DisplayObjectContainer"
/>
<
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"
/>
<
accessor
name
="hitArea"
access
="readwrite"
type
="flash.display::Sprite"
declaredBy
="flash.display::Sprite"
/>
<
method
name
="startDrag"
declaredBy
="flash.display::Sprite"
returnType
="void"
>
<
parameter
index
="1"
type
="Boolean"
optional
="true"
/>
<
parameter
index
="2"
type
="flash.geom::Rectangle"
optional
="true"
/>
</
method
>
<
accessor
name
="buttonMode"
access
="readwrite"
type
="Boolean"
declaredBy
="flash.display::Sprite"
/>
<
accessor
name
="graphics"
access
="readonly"
type
="flash.display::Graphics"
declaredBy
="flash.display::Sprite"
/>
<
accessor
name
="soundTransform"
access
="readwrite"
type
="flash.media::SoundTransform"
declaredBy
="flash.display::Sprite"
/>
<
method
name
="stopDrag"
declaredBy
="flash.display::Sprite"
returnType
="void"
/>
<
accessor
name
="dropTarget"
access
="readonly"
type
="flash.display::DisplayObject"
declaredBy
="flash.display::Sprite"
/>
<
accessor
name
="useHandCursor"
access
="readwrite"
type
="Boolean"
declaredBy
="flash.display::Sprite"
/>
<
method
name
="getChildAt"
declaredBy
="flash.display::DisplayObjectContainer"
returnType
="flash.display::DisplayObject"
>
<
parameter
index
="1"
type
="int"
optional
="false"
/>
</
method
>
<
method
name
="addChild"
declaredBy
="flash.display::DisplayObjectContainer"
returnType
="flash.display::DisplayObject"
>
<
parameter
index
="1"
type
="flash.display::DisplayObject"
optional
="false"
/>
</
method
>
<
method
name
="swapChildren"
declaredBy
="flash.display::DisplayObjectContainer"
returnType
="void"
>
<
parameter
index
="1"
type
="flash.display::DisplayObject"
optional
="false"
/>
<
parameter
index
="2"
type
="flash.display::DisplayObject"
optional
="false"
/>
</
method
>
<
method
name
="getChildByName"
declaredBy
="flash.display::DisplayObjectContainer"
returnType
="flash.display::DisplayObject"
>
<
parameter
index
="1"
type
="String"
optional
="false"
/>
</
method
>
<
method
name
="getObjectsUnderPoint"
declaredBy
="flash.display::DisplayObjectContainer"
returnType
="Array"
>
<
parameter
index
="1"
type
="flash.geom::Point"
optional
="false"
/>
</
method
>
<
accessor
name
="textSnapshot"
access
="readonly"
type
="flash.text::TextSnapshot"
declaredBy
="flash.display::DisplayObjectContainer"
/>
<
method
name
="removeChildAt"
declaredBy
="flash.display::DisplayObjectContainer"
returnType
="flash.display::DisplayObject"
>
<
parameter
index
="1"
type
="int"
optional
="false"
/>
</
method
>
<
method
name
="getChildIndex"
declaredBy
="flash.display::DisplayObjectContainer"
returnType
="int"
>
<
parameter
index
="1"
type
="flash.display::DisplayObject"
optional
="false"
/>
</
method
>
<
method
name
="areInaccessibleObjectsUnderPoint"
declaredBy
="flash.display::DisplayObjectContainer"
returnType
="Boolean"
>
<
parameter
index
="1"
type
="flash.geom::Point"
optional
="false"
/>
</
method
>
<
accessor
name
="mouseChildren"
access
="readwrite"
type
="Boolean"
declaredBy
="flash.display::DisplayObjectContainer"
/>
<
method
name
="removeChild"
declaredBy
="flash.display::DisplayObjectContainer"
returnType
="flash.display::DisplayObject"
>
<
parameter
index
="1"
type
="flash.display::DisplayObject"
optional
="false"
/>
</
method
>
<
method
name
="setChildIndex"
declaredBy
="flash.display::DisplayObjectContainer"
returnType
="void"
>
<
parameter
index
="1"
type
="flash.display::DisplayObject"
optional
="false"
/>
<
parameter
index
="2"
type
="int"
optional
="false"
/>
</
method
>
<
method
name
="contains"
declaredBy
="flash.display::DisplayObjectContainer"
returnType
="Boolean"
>
<
parameter
index
="1"
type
="flash.display::DisplayObject"
optional
="false"
/>
</
method
>
<
method
name
="addChildAt"
declaredBy
="flash.display::DisplayObjectContainer"
returnType
="flash.display::DisplayObject"
>
<
parameter
index
="1"
type
="flash.display::DisplayObject"
optional
="false"
/>
<
parameter
index
="2"
type
="int"
optional
="false"
/>
</
method
>
<
accessor
name
="numChildren"
access
="readonly"
type
="int"
declaredBy
="flash.display::DisplayObjectContainer"
/>
<
method
name
="swapChildrenAt"
declaredBy
="flash.display::DisplayObjectContainer"
returnType
="void"
>
<
parameter
index
="1"
type
="int"
optional
="false"
/>
<
parameter
index
="2"
type
="int"
optional
="false"
/>
</
method
>
<
accessor
name
="tabChildren"
access
="readwrite"
type
="Boolean"
declaredBy
="flash.display::DisplayObjectContainer"
/>
<
accessor
name
="tabEnabled"
access
="readwrite"
type
="Boolean"
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
="accessibilityImplementation"
access
="readwrite"
type
="flash.accessibility::AccessibilityImplementation"
declaredBy
="flash.display::InteractiveObject"
>
<
metadata
name
="Inspectable"
>
<
arg
key
="environment"
value
="none"
/>
</
metadata
>
</
accessor
>
<
accessor
name
="mouseEnabled"
access
="readwrite"
type
="Boolean"
declaredBy
="flash.display::InteractiveObject"
/>
<
accessor
name
="focusRect"
access
="readwrite"
type
="Object"
declaredBy
="flash.display::InteractiveObject"
/>
<
accessor
name
="tabIndex"
access
="readwrite"
type
="int"
declaredBy
="flash.display::InteractiveObject"
/>
<
accessor
name
="mask"
access
="readwrite"
type
="flash.display::DisplayObject"
declaredBy
="flash.display::DisplayObject"
/>
<
accessor
name
="scaleX"
access
="readwrite"
type
="Number"
declaredBy
="flash.display::DisplayObject"
/>
<
accessor
name
="scaleY"
access
="readwrite"
type
="Number"
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
="mouseY"
access
="readonly"
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
="name"
access
="readwrite"
type
="String"
declaredBy
="flash.display::DisplayObject"
/>
<
accessor
name
="y"
access
="readwrite"
type
="Number"
declaredBy
="flash.display::DisplayObject"
/>
<
accessor
name
="root"
access
="readonly"
type
="flash.display::DisplayObject"
declaredBy
="flash.display::DisplayObject"
/>
<
accessor
name
="width"
access
="readwrite"
type
="Number"
declaredBy
="flash.display::DisplayObject"
/>
<
accessor
name
="stage"
access
="readonly"
type
="flash.display::Stage"
declaredBy
="flash.display::DisplayObject"
/>
<
accessor
name
="loaderInfo"
access
="readonly"
type
="flash.display::LoaderInfo"
declaredBy
="flash.display::DisplayObject"
/>
<
accessor
name
="transform"
access
="readwrite"
type
="flash.geom::Transform"
declaredBy
="flash.display::DisplayObject"
/>
<
accessor
name
="height"
access
="readwrite"
type
="Number"
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
>
<
accessor
name
="filters"
access
="readwrite"
type
="Array"
declaredBy
="flash.display::DisplayObject"
/>
<
accessor
name
="blendMode"
access
="readwrite"
type
="String"
declaredBy
="flash.display::DisplayObject"
/>
<
accessor
name
="rotation"
access
="readwrite"
type
="Number"
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
="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
="cacheAsBitmap"
access
="readwrite"
type
="Boolean"
declaredBy
="flash.display::DisplayObject"
/>
<
method
name
="globalToLocal"
declaredBy
="flash.display::DisplayObject"
returnType
="flash.geom::Point"
>
<
parameter
index
="1"
type
="flash.geom::Point"
optional
="false"
/>
</
method
>
<
method
name
="getBounds"
declaredBy
="flash.display::DisplayObject"
returnType
="flash.geom::Rectangle"
>
<
parameter
index
="1"
type
="flash.display::DisplayObject"
optional
="false"
/>
</
method
>
<
accessor
name
="opaqueBackground"
access
="readwrite"
type
="Object"
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
="visible"
access
="readwrite"
type
="Boolean"
declaredBy
="flash.display::DisplayObject"
/>
<
accessor
name
="mouseX"
access
="readonly"
type
="Number"
declaredBy
="flash.display::DisplayObject"
/>
<
method
name
="willTrigger"
declaredBy
="flash.events::EventDispatcher"
returnType
="Boolean"
>
<
parameter
index
="1"
type
="String"
optional
="false"
/>
</
method
>
<
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
="toString"
declaredBy
="flash.events::EventDispatcher"
returnType
="String"
/>
<
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
>
<
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
>
</
type
>
所有的标签与之前 factory 标签中的内容是一样的
现在我们使用 describeType 来遍历之前 Dummy 类中的元素
实例化:
var dummy:Dummy = new Dummy();
获取实例信息:
var instanceInfo:XML = describeType(dummy);
把所有的属性取出来, 包括访问器和变量, 并且访问器不可为只写:
var properties:XMLList = instanceInfo..accessor.(@access != "writeonly") + instanceInfo..variable;
此时 properties 里就有所有的属性名了. 最后我们遍历这个 XMLList
for each (var propertyInfo:XML in properties) {
// 取出属性名
var propertyName:String = propertyInfo.@name;
// 根据属性名来访问
trace(dummy[propertyName]);
}
这样 dummy 就被 "遍历" 出了~
完整代码:
var dummy:Dummy = new Dummy();
var instanceInfo:XML = describeType(dummy);
var properties:XMLList = instanceInfo..accessor.(@access != "writeonly") + instanceInfo..variable;
for each (var propertyInfo:XML in properties) {
var propertyName:String = propertyInfo.@name;
trace(dummy[propertyName]);
}
这样我们可以专门写一个类, 负责获取类信息, 详细见类中注释
TypeDescriptor.as, 负责获取信息
package
{
import flash.utils.describeType;
import flash.utils.getQualifiedClassName;
import flash.utils.getDefinitionByName;
/**
* 使用 flash.utils.describeType 获取类详细信息并缓存
* @author kakera
*
*/
public class TypeDescriptor
{
/**
* 缓存已经反射过了的对象
*/
private static var typeCache:Object = new Object();

/**
* 获取类信息
* @param target 要获取的目标对象
* @return TypeDescriptorEntry 实例
*
*/
public static function describeType (target:*):TypeDescription {

var className:String = getQualifiedClassName(target);

/**
* 检查缓存中是否已经有目标对象项, 如果有就返回缓存中的内容
*/
if (className in typeCache)
return typeCache[className];
/**
* 暂存属性列表
*/
var propertyNames:Array = [];

/**
* 获取类信息, 如果传入的是实例则获取实例类型的类信息
*/
var typeInfo:XML = flash.utils.describeType(target is Class ? target : getDefinitionByName(className) as Class);
/**
* 获取类中所有的属性和访问器
*/
var properties:XMLList = typeInfo.factory..accessor.(@access != "writeonly") + typeInfo..variable;

/**
* 遍历并存放到 propertyNames 中
*/
for each (var propertyInfo:XML in properties)
propertyNames.push(propertyInfo.@name);
/**
* 创建 TypeDescriptorEntry 的实例并把 propertyNames 等属性丢进去
*/
var entry:TypeDescription = new TypeDescription();
entry.name = className;
entry.properties = propertyNames;
entry.typeInfo = typeInfo;
/**
* 缓存到 typeCache 中以便下次从缓存中读取
*/
typeCache[className] = entry;
return entry;
}
/**
* 静态类无须实例化
* @return
*
*/
public function TypeDescriptor () { }
}
}
TypeDescription.as, 负责保存信息
package
{
public class TypeDescription
{
/**
* 类的属性列表, 包括访问器 (accessor) 和变量 (variable)
*/
public var properties:Array; /* of String */
/**
* 类名
*/
public var name:String;


/**
* 由 flash.utils.describeType() 获取的原始 XML 数据
*/
public var typeInfo:XML;

public function TypeDescription () { }
}
}