AS3的反射机制

什么是反射
反射 (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>&lt;type&gt;</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>&lt;extendsClass&gt;</code></td><td> </td><td>使用 <code>extendsClass</code> 标签分别存放当前 ActionScript 对象的超类</td></tr>
      <tr><td> </td><td>type</td><td>当前 ActionScript 对象所继承的超类的名字</td></tr>
      <tr><td><code>&lt;implementsInterface&gt;</code></td><td> </td><td>使用 <code>implementsInterface</code> 标签分别存放当前 ActionScript 对象, 以及他的超类所实现的接口</td></tr>
      <tr><td> </td><td>type</td><td>当前 ActionScript 所实现的接口的名字</td></tr>
      <tr><td><code>&lt;accessor&gt;</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>&lt;constant&gt;</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>&lt;method&gt;</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>&lt;parameter&gt;</code></td><td> </td><td>使用 <code>parameter</code> 分别存放该方法的参数, 该标签被嵌套在 <code>&lt;method&gt;</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>&lt;variable&gt;</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>&lt;factory&gt;</code></td><td> </td><td>如果当前 ActionScript 对象是类对象或者构造函数, 所有的实例属性将会被嵌套进该标签. 如果 <code>&lt;type&gt;</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> 标签里.

我们再试一下获取实例的信息 :

<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 = [email protected];

    // 根据属性名来访问
    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 = [email protected];
    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([email protected]);

            /**
            * 创建 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 () { }
    }
}
时间: 2024-10-05 06:19:34

AS3的反射机制的相关文章

Android小例子:使用反射机制来读取图片制作一个图片浏览器

效果图: 工程文件夹: 该例子可供于新手参考练习,如果有哪里不对的地方,望指正>-< <黑幕下的人> java代码(MainActivity.java): package com.example.imageswitchtest; import java.lang.reflect.Field; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.v

java反射机制(一)—— 利用反射机制实例化对象

一.Java有着一个非常突出的动态相关机制:Reflection,用在Java身上指的是我们可以于运行时加载.探知.使用编译期间完全未知的classes.换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体.或对其fields设值.或唤起其methods.(度娘文库是这么说的) 二.这篇文章主要介绍一下通过反射机制去实例化一个类的对象,然后调用其方法.本文主要介绍两种方式,第一种就是通过构造函数来实例化,第二种就是通过Cl

Java反射机制

Java的反射机制概念 主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义. 反射是java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接.但是反射使用不当会成本很高! 反射的作用 1 可以反编译将class文件编译成java文件 2 可以通过反射机制访问Java对象的属性,方法,构造方法等 反射机制使用步骤 1 得到要调用类的class 2 通过得到的c

【java】java反射机制,动态获取对象的属性和对应的参数值,并属性按照字典序排序,Field.setAccessible()方法的说明【可用于微信支付 签名生成】

方法1:通过get()方法获取属性值 package com.sxd.test.controller; public class FirstCa{ private Integer num; private String name; private Boolean flag; public Integer getNum() { return num; } public void setNum(Integer num) { this.num = num; } public String getNam

使用反射机制调用属性和私有成员与代理模式的介绍

使用反射机制调用属性: 通过反射机制可以获得类的属性,获得到的属性同样的可以进行赋值.得值操作,调用getField方法并传递属性的名称可以获得[学Java,到凯哥学堂kaige123.com]指定的属性,调用getFields方法则可以获得全部属性,但是这种方式不能获得私有属性: 代码示例: Student类示例: 运行结果: 从运行结果可以看出只拿出了公开的属性,私有的属性拿不到. 使用反射机制调用私有成员: 1.调用私有属性 在反射机制里调用私有属性需要通过getDeclaredField

反射机制

反射机制: 反射机制是能够帮助我们把代码变得更加灵活,可扩展性更高,俗称"软编程.软写法".例如:有一个文件里面有一些值,想要把这些值赋值到一个Student类的属性中,按照以前所学到的知识点,只能是通过文件流将文件里的值读取出来,然后再通过set方法将这些值都赋给Student类的属性.但是,这种方式是将代码写死了,在这之后会有一个问题就是如果文件里的内容发生变动,或者要把这个Student类更换成Dog类的话,就要重新修改代码.程序写好了部署到服务器上运行了,总不能时不时就打开来修

Python学习心得(六) 反射机制、装饰器

1.反射机制 #/usr/bin/env python # -*- coding:utf-8 -*- ''' Python反射机制的核心本质:利用字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员,一种基于字符串的事件驱动 通俗讲就是通过用户传入url的不同,调用不同的模块函数,好多比较流行的web框架都是通过反射的机制,根据url的不同指向不同的模块 getattr(),hasattr(),setattr(),delattr()对模块的修改都在内存中进行,并不会影响文件中的真实内容

Java 反射机制

使用 Java 反射机制可以在运行时期检查 Java 类的信息,检查 Java 类的信息往往是你在使用 Java 反射机制的时候所做的第一件事情,通过获取类的信息你可以获取以下相关的内容: Class 对象 类名 修饰符 包信息 父类 实现的接口 构造器 方法 变量 注解 除了上述这些内容,还有很多的信息你可以通过反射机制获得,如果你想要知道全部的信息你可以查看相应的文档 JavaDoc for java.lang.Class 里面有详尽的描述. 在本节中我们会简短的涉及上述所提及的信息,上述的

Java的反射机制简述

反射机制是Java语言中一个非常重要的特性,它允许程序在运行时进行自我检查,同时也允许内部的成员进行操作.虽然这个特性在实际开发中使用的不多,但是像Pascal.C和C++等语言根本没有提供这样的特性.由于反射机制能够实现在运行时对类进行装载,因此能够增加程序的灵活性,但是不恰当地使用反射机制也会严重影响系统的性能. 具体而言,反射机制提供的功能主要有: 1.得到一个对象所属的类: 2.获取一个类的所有成员变量和方法: 3.在运行时创建对象: 4.在运行时调用对象的方法. 其实,反射机制非常重要