zoukankan      html  css  js  c++  java
  • 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 );
            }
        }
    }

     

    最后测试 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(
    00100100);
                sprite2.graphics.endFill();
                addChild(sprite2);
            }
            

        }
    }

     

  • 相关阅读:
    [leetcode-648-Replace Words]
    [leetcode-647-Palindromic Substrings]
    [leetcode-646-Maximum Length of Pair Chain]
    [leetcode-645-Set Mismatch]
    [leetcode-459-Repeated Substring Pattern]
    [leetcode-636-Exclusive Time of Functions]
    [leetcode-644-Maximum Average Subarray II]
    iOS开发之使用XMPPFramework实现即时通信(三)
    Oracle 内置sql函数大全
    Oracle 中的sql函数以及分页
  • 原文地址:https://www.cnblogs.com/daidu/p/1619111.html
Copyright © 2011-2022 走看看