- 浏览: 101981 次
- 性别:
- 来自: 大连
文章分类
最新评论
什么是反射
反射 (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
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 模式. 控制台中只会出现
测试 for..in 循环, 遍历 Dummy 的实例
显然 dummy 中的元素都没有被遍历出
在 as1, 2 中很简单就可以实现的问题在 as3 得换个办法了, 谁让他们是传统的脚本语言呢
而在 as3 中, 就得通过反射来解决这个问题了. 方法会在文后介绍
动态创建实例
* 这部分内容帮助中已经有例子, 我摘要一些翻译一下, 不过我的 e 文很烂. 希望大家能看得懂.
as3 使用 flash.util.getDefinitionByName 动态获取类 (Class) 引用
帮助中该方法的描述 :
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, 这个方法返回的是字符串
public function getQualifiedClassName(value:*):String
返回类的完全限定名 (fully qualified class name, qualified 我不知道怎么翻了..)
参数 value:* - 想要得到完全限定名的对象. 他可以是任何 ActionScript 类型, 对象实例, 简单类型如 uint 以及类类型.
返回 String - 包含类的完全限定名的字符串
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);
} } }
获取类信息
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>
所有的标签与之前 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 () { }
}
}
反射 (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
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 模式. 控制台中只会出现
测试 for..in 循环, 遍历 Dummy 的实例
显然 dummy 中的元素都没有被遍历出
在 as1, 2 中很简单就可以实现的问题在 as3 得换个办法了, 谁让他们是传统的脚本语言呢
而在 as3 中, 就得通过反射来解决这个问题了. 方法会在文后介绍
动态创建实例
* 这部分内容帮助中已经有例子, 我摘要一些翻译一下, 不过我的 e 文很烂. 希望大家能看得懂.
as3 使用 flash.util.getDefinitionByName 动态获取类 (Class) 引用
帮助中该方法的描述 :
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, 这个方法返回的是字符串
public function getQualifiedClassName(value:*):String
返回类的完全限定名 (fully qualified class name, qualified 我不知道怎么翻了..)
参数 value:* - 想要得到完全限定名的对象. 他可以是任何 ActionScript 类型, 对象实例, 简单类型如 uint 以及类类型.
返回 String - 包含类的完全限定名的字符串
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);
} } }
获取类信息
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>
所有的标签与之前 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 () { }
}
}
发表评论
-
AS3 经典的代码库
2013-03-29 16:39 03D引擎 Papervision3Dhttp://b ... -
AS3开源资源整理
2013-03-29 16:38 0一个使用Stage3D APIs 实现 ... -
如何自定义VideoPlayer的全屏行为
2012-12-13 16:58 1311Flex4中增加了一个视频播放组件:VideoPlayer,相 ... -
代码改变影片剪辑亮度、色调、高级、透明度的方法
2012-12-03 08:41 867通过Color类来改变影片颜色 亮度:(设置影片明暗效果) ... -
as3自己写皮肤
2012-11-30 09:47 0<?xml version="1.0" ... -
AS3 正则表达式详解
2012-11-30 09:27 01.新建正则表达式,有两 ... -
TweenLite用法
2012-11-30 09:26 0TweenLite 是一个缓动的类 ... -
AS3位图的加载、拷贝、绘制
2012-11-30 09:26 0建Bitmap可以是使用Bitmap ... -
AS3文本操作
2012-11-30 09:03 1226设置文本框的边框、背景与前景色 默认状态下,文本框的边框和背景 ... -
as3日期格式化以及htmlText的安全转义类
2012-11-30 08:57 1036package org.juke{ ... -
Flash AS3.0关于TextField的过滤,HTML格式,对齐,换行等介绍
2012-11-30 08:56 1375过滤文字输入 TextField.restrict = &q ... -
AS3碎裂重组特效
2012-11-26 15:04 884碎裂指的是图片的碎裂 那我们要先做的是就是得到这张图片,在a ... -
Flash AS3.0实例---接近鼠标的图片缓动效果
2012-11-26 15:02 1178当鼠标移动到图片的一定位置时,图片会缓冲移动到鼠标位置,在现 ... -
flex air 启动本地应用程序
2012-11-26 09:23 854在air 2.0中,可以利用NativeProcess启动本地 ... -
as3打开和保存本地文件
2012-11-26 08:52 2394package { import flash.displa ... -
FLV视频类播放器全屏切换完整AS代码示例
2012-11-21 10:53 825function setFullScreen() { ... -
as3冒泡排序
2012-11-20 09:12 0<?xml version="1.0" ... -
Flex在Image组件使用蒙板
2012-11-16 17:34 0Flex在Image组件使用蒙板 1.Flex SDK3.0 ... -
Flex导入Excel文件示例
2012-11-16 17:33 01.SDK3.0 2.导入文件用FileFilter过滤。由于 ... -
Flash as3把2D图片分析成文本实现代码
2012-11-16 17:32 0一篇在游戏开发中常用到的功能就是利用as3把2D图片分析成文本 ...
相关推荐
在AS3中,反射是一种强大的工具,可以帮助开发人员实现高度灵活和动态的代码。然而,它的使用需要谨慎,因为它可能会引入潜在的性能问题和安全风险。正确理解和应用反射,可以在许多场景下提高代码的适应性和功能。
在AS3中,XML是一种常见的数据交换格式,XML转换类可以帮助解析XML文档,并根据其结构创建相应的AS3对象。这个过程通常涉及到递归遍历XML节点,为每个节点创建对应的属性或子对象,对于XML属性则映射到对象的属性值...
As2Commons通过`org.as3commons.reflect`包提供了一系列的反射API,下面我们来详细介绍其中几个重要的类和接口: 1. **`Type`**:代表一个类或接口的信息,包含了很多方法用于获取该类型的各种信息,如字段、构造...
标题中的“3D立体展示图片-附as3源码”表明这是一个使用...这个3D立体展示图片项目是一个很好的学习资源,可以帮助开发者深入了解AS3中的3D图形编程,同时也可以作为一个起点,探索更复杂的3D应用程序的开发。
在Flash AS3中,3D立体墙是一种交互式的可视化技术,它允许用户以三维的方式浏览和操作元素,比如图片、视频或图标。这种技术在网页设计、游戏开发以及数据展示等领域有着广泛的应用。以下是关于“Flash AS3 3D立体...
在AS3中,我们可以通过创建动态的二维数组来存储水面的每个像素的高度,然后随着时间的推移更新这些值以模拟波动。 为了创建逼真的水波效果,我们需要考虑以下关键因素: 1. **扰动源**:在AS3中,你可以通过监听...
在AS3中,这可能通过比较物体在视口中的Z坐标或使用深度缓冲(Z-Buffer)实现。深度缓冲是一种像素级别的渲染技术,用于存储每个像素的深度值,以决定哪个物体应该在前景,哪个在背景。 再者,"光照系统"是3D游戏...
说明:这个是用来实现已在场景中的Mc复制多个出来,如AS2中可以duplicateMovieClip,AS3中用是用New和addChild的, 有人会说As3可以用 方法1——反射方法: var ClassRef:Class = getDefinitionByName...
尽管如此,通过巧妙的算法优化,可以在AS3中实现光线追踪。 光线追踪的基本原理是模拟光线从眼睛出发,穿过虚拟场景,并与场景中的物体交互,如反射、折射和吸收。这个过程涉及到以下几个关键概念: 1. **光线投射...
在AS3中,我们可以添加`Event.MOUSE_DOWN`事件监听器,并在事件处理函数中执行旋转操作。 4. **视图控制**:为了展示魔方的旋转,我们需要一个相机来观察3D场景。PV3D提供了`Camera3D`类,可以设置其位置和方向,...
在Flash Player的支持下,ASGL使得开发者能够利用ActionScript 3(AS3)编程语言构建复杂的3D应用,如游戏、模拟器、数据可视化工具等。 在ASGL中,核心概念包括场景(Scene)、相机(Camera)、光源(Light)、...
在AS3.0版本中,引入了反射机制,这是一个强大的工具,允许程序在运行时检查自身并操作其内部结构,如类、属性、方法等。本压缩包文件"flash反射实例"提供了关于AS3.0反射机制的实际应用示例,对于想要深入了解和...
在Kotlin编程中,反射是一种强大的工具,它允许我们在运行时检查类、接口、属性和方法等信息,甚至可以动态地调用它们。然而,由于Kotlin与Java反射的实现方式有所不同,开发者在使用过程中可能会遇到一些特定的问题...
- **反射与动态类型**:Java 的反射在 AS3 中较弱,转换时可能需要避免或重构涉及反射的部分。 4. **源码与工具的配合** 转换过程中,你可能会遇到源码中的一些特殊结构或库依赖,这时需要对 Java 和 AS3 两者的...
在一个BGP域中,一个路由器通过IBGP从另一个路由器学习到的路由信息是不会转发给下一个IBGP路由器的,这是为了避免在AS中产生路由环路。为了克服这个问题,我们定义了路由反射器的概念。一台被配置为路由反射器的...
在标题和描述中,"pv3d开发工具as3 编写"表明这是一个使用AS3开发的PV3D工具集或框架,可能是为了简化和加速3D内容的创建。这样的工具可能包括类库、示例代码、调试工具、编辑器插件等,旨在帮助开发者更好地理解和...
在.NET框架中,反射是一个强大的工具,它允许程序在运行时检查自身和其他程序集的元数据,从而实现动态类型操作、实例化对象、调用方法、访问字段等。本参考手册将深入探讨如何在Visual Basic .NET中有效地利用反射...
在VB.NET编程中,反射是一种强大的机制,它允许运行时检查和操作程序集、类型、方法、属性等元数据。这个“VB.NET 反射 示例Demo(项目用)”是专为初学者设计的,旨在帮助理解如何在实际项目中应用反射。下面将详细...
在这个场景中,我们关注的是使用BGP反射器在MPLS环境中的应用。BGP反射器是一种优化BGP路由传播的方法,尤其在大型网络中,它能够减少路由更新的复杂性和网络带宽的需求。 **MPLS** 是一种在IP网络上提供服务质量...
3. **访问成员**:反射允许我们动态地访问类的成员,如字段、属性、方法和事件。使用`GetFields()`, `GetProperties()`, `GetMethod()`, `GetEvents()`等方法可以获取这些成员,并通过`SetValue()`和`Invoke()`进行...