AS3 设置在运行时更改类类型

发布于 2024-10-22 05:55:34 字数 715 浏览 1 评论 0原文

我有一个类并使用 flash.utils.describeType(this) 跟踪其类型

class Data extends EventDispatcher
        {
        public function Data()
            {
            //constructor
            }

        public override function toString():String
            {
            return describeType(this);
            }
        }


<type name="Data" base="flash.events::EventDispatcher" isDynamic="false" isFinal="false" isStatic="false">
    <extendsClass type="flash.events::EventDispatcher"/>
    <extendsClass type="Object"/>
    <implementsInterface type="flash.events::IEventDispatcher"/>
    </type>

是否可以在运行时覆盖此信息,例如 type.@isDynamic 以及 extendsClass.@type? 没有字节码?

i have a class and trace its type with flash.utils.describeType(this)

class Data extends EventDispatcher
        {
        public function Data()
            {
            //constructor
            }

        public override function toString():String
            {
            return describeType(this);
            }
        }


<type name="Data" base="flash.events::EventDispatcher" isDynamic="false" isFinal="false" isStatic="false">
    <extendsClass type="flash.events::EventDispatcher"/>
    <extendsClass type="Object"/>
    <implementsInterface type="flash.events::IEventDispatcher"/>
    </type>

Is it possible to override this information e.g type.@isDynamic, as well as extendsClass.@type, at runtime?
without bytecode?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

ヤ经典坏疍 2024-10-29 05:55:34

执行此操作的最佳替代方法是使用组合并仅封装您需要的类。这样您就可以避免使用动态关键字以及更改扩展值的需要。

public class Data extends TheClassYouNeedToExtend
{
    private var encapsulated : TheRealData;

    private var value : int;

    public function Data()
    {
        encapsulated = new TheRealData;
    }

    public function get dynamicValue() : int
    {
        return value;
    }

    public function get dataValue() : int
    {
        return encapsulated.value;
    }
}

The best alternative to doing this, is to use composition and just encapsulate the class you need. That way you can avoid the dynamic keyword and the need to change the extension value.

public class Data extends TheClassYouNeedToExtend
{
    private var encapsulated : TheRealData;

    private var value : int;

    public function Data()
    {
        encapsulated = new TheRealData;
    }

    public function get dynamicValue() : int
    {
        return value;
    }

    public function get dataValue() : int
    {
        return encapsulated.value;
    }
}
养猫人 2024-10-29 05:55:34

不,XML 基于类加载时字节码中的特征。您无法通过加载新类来覆盖类,因此您只能使用类的第一个定义。

No, the xml is based on the traits in the bytecode when the class is loaded. You cannot override classes by loading in new ones, so you are stuck with the first definition of the class.

蓝天白云 2024-10-29 05:55:34

在运行时扩展两个类不是问题。
我昨晚写了一个例子,但它不是没有错误的自动取款机,因为我现在不需要它。

使用描述类型非常容易。我无法摆脱动态,但这不是问题。
我在这台电脑上没有我的示例,这是我可以根据自己的想法做出的:

//D == public dynamic class;
var C:Class = extend(D,EventDispatcher);


function _new(A)
{
if(A.prototype.extend)
  {
  //hehe
  for(var i in A.prototype.extend)
    {
    //BANG!
    //copy proterties
    }
  return new A();
  }
else return new A();
}


function extend(A,B,b=false)
{
var C = A;

if(!b)
 {
 C = xtend(C,B,xml.extendClass);
 C = xtend(C,A,xml.extendClass);
 }

C = copy(C,B,xml.constant);
C = copy(C,A,xml.constant);
C = copy(C,B,xml.variable);
C = copy(C,A,xml.variable);

return C;
}


function xtend(A,B,xml)
{
for(var i in xml)
    {
    var C:Class = Class(getDefinitionByName(xml[xml.length()-Number(i)-1]));
    A = extend(A,C,true);

    if(!A.prototype.extend) A.prototype.extend = [];
    A.prototype.extend.push(C);
    }

A.prototype.extend = A.prototype.extend.unique();
return A;
}


function copy(A,B,xml)
{
for each(var node in xml)
    A[node.@name] = B[node.@name];

return A;
}

它将是一个 200-300 行的解决方案。

its not a problem to extend two classes at runtime.
I worte an example last evenning but its not bugfree atm because im not going to need it now.

its very easy with describe type. i cant get rid of the dynamic but thats not a problem.
i dont have my example on this pc, here is what i can make up from my mind:

//D == public dynamic class;
var C:Class = extend(D,EventDispatcher);


function _new(A)
{
if(A.prototype.extend)
  {
  //hehe
  for(var i in A.prototype.extend)
    {
    //BANG!
    //copy proterties
    }
  return new A();
  }
else return new A();
}


function extend(A,B,b=false)
{
var C = A;

if(!b)
 {
 C = xtend(C,B,xml.extendClass);
 C = xtend(C,A,xml.extendClass);
 }

C = copy(C,B,xml.constant);
C = copy(C,A,xml.constant);
C = copy(C,B,xml.variable);
C = copy(C,A,xml.variable);

return C;
}


function xtend(A,B,xml)
{
for(var i in xml)
    {
    var C:Class = Class(getDefinitionByName(xml[xml.length()-Number(i)-1]));
    A = extend(A,C,true);

    if(!A.prototype.extend) A.prototype.extend = [];
    A.prototype.extend.push(C);
    }

A.prototype.extend = A.prototype.extend.unique();
return A;
}


function copy(A,B,xml)
{
for each(var node in xml)
    A[node.@name] = B[node.@name];

return A;
}

its going to be a 200-300 line solution.

So尛奶瓶 2024-10-29 05:55:34

有一种方法可以做你想做的事,但在解释它之前,我想说几件事:

1)这不是最佳实践 - 代码以它的方式工作是有原因的,并且任何当您觉得需要改变 AS3 的整个工作方式(例如,在运行时将类更改为动态类)时,最好坐下来思考这是否真的是最好的做法。很可能有一种现有的设计模式可以帮助您解决您想要解决的特定问题。

2)如果您使用我即将与您分享的秘密,那么其他用户几乎不可能理解您的代码。也许您正在一个业余爱好项目上独自工作,这很好 - 但如果您在一个团队中,或者您是一大群人中的一员,对一个非常复杂的项目进行更新,请为每个接触的人做好准备这段代码在你做完之后诅咒你的名字。 :)

那就是说,准备好了吗?

您可以通过修改类的 .prototype 属性来更改类的行为。例如,假设我有类 MyClass,它只有一个方法“myMethod()”。但无论出于何种原因,在运行时我需要向类添加一个新方法(“myNewMethod()”)。

我通过在我正在使用的任何类中创建一个名为“myNewMethod()”的函数来实现这一点。然后我将该函数的引用传递给 MyClass 的原型。请注意,因为您在这里违反了规则,所以您将必须使用字符串文字作为函数名称以避免编译器错误。

这是一个代码示例:

var test1:MyClass = new MyClass();
test1.myMethod() // works just fine
test1.anotherMethod() // compiler error - this method does not exist in MyClass! Can't compile.

MyClass.prototype["anotherMethod"] = function ():void { trace("anotherMethod!"); }

test1.anotherMethod(); // error - as far as the compiler knows, anotherMethod doesn't exist. Still can't compile.

test1["anotherMethod"]() // this works!

很酷,对吧?

也就是说,除非您知道自己在做什么,否则不要在生产代码中执行此操作!有更好的方法可以实现类似的结果,您的队友可能会感谢您。

There is a way to do what you want to do, but before I explain it I'd like to say a few things:

1) This is NOT a best practice - there is a reason that code works the way it works, and any time you feel like you need to change the entire way AS3 works (like by changing a class to dynamic at runtime, for instance) then it's a very good idea to sit down and figure out if that's really the best thing to do. Odds are there's an existing design pattern that will help you solve the specific problem you're trying to solve.

2) If you use the secrets I'm about to share with you then it's going to become next to impossible for other users to make sense of your code. Maybe you're working solo on a hobby project and this is fine - but if you're on a team, or if you're one of a long set of people making updates to a very complex project, be prepared for everyone who touches this code after you do to curse your name. :)

That said, ready?

You can change the behavior of a class by modifying its .prototype property. For instance, let's say I have class MyClass which has only one method, "myMethod()". But for whatever reason, at runtime I need to add a new method ("myNewMethod()") to the class.

I do that by creating a function called "myNewMethod()" in whatever class I'm working in. Then I pass a reference to that function to the prototype of MyClass. Note that because you're bending the rules here you're going to have to use string literals as your function names to avoid compiler errors.

Here's a code sample:

var test1:MyClass = new MyClass();
test1.myMethod() // works just fine
test1.anotherMethod() // compiler error - this method does not exist in MyClass! Can't compile.

MyClass.prototype["anotherMethod"] = function ():void { trace("anotherMethod!"); }

test1.anotherMethod(); // error - as far as the compiler knows, anotherMethod doesn't exist. Still can't compile.

test1["anotherMethod"]() // this works!

Pretty cool, huh?

That said, DO NOT DO THIS IN PRODUCTION CODE UNLESS YOU KNOW WHAT YOU'RE DOING! There are better ways to achieve similar results, and your teammates will probably thank you.

爱已欠费 2024-10-29 05:55:34

现在它的工作。最后一篇文章对于香蕉的某些部分来说有点可耻。
这就是为什么我又丢了一封信。对于访问器,我必须走很长的路。老派的 javascript...


{
导入 flash.display.DisplayObject;
导入 flash.display.Sprite;
导入 flash.events.Event;
导入 flash.utils.getDefinitionByName;
导入 flash.utils.getQualifiedClassName;
导入 flash.utils.describeType;

public class Main extends Sprite 
    {

    public function Main():void 
        {
        if (stage) init();
        else addEventListener(Event.ADDED_TO_STAGE, init);
        }

    private function init(e:Event = null):void 
        {
        removeEventListener(Event.ADDED_TO_STAGE, init);

        var C:Class = Class(extend(D, Sprite));
        var O:Object = _new(C);

        var s:Sprite = new Sprite();
        O.addEventListener('asddas',event);
        O.dispatchEvent(new Event('asddas'));
        O.addChild(s);

        O.graphics.clear();
        O.graphics.beginFill(0x000000,1);
        O.graphics.lineStyle(1, 0x000000, 1, true, "none"); 
        O.graphics.drawRect(0, 0, 100, 100);
        O.graphics.endFill();       

        trace(O.getChildAt(0), O.numChildren, O.width, O.prototype.extend.width, O.hasEventListener('asddas'), O.willTrigger('asddas'), O.mouseY, O.mouseEnabled);

        addChild(O.prototype.extend);
        }   


    private function event(e:Object):void
        {
        trace(e.type);
        }

    private function _new(A:Class):Object
        {
        if (A.prototype.extend)
            {
            var O:Object = new A();
            var E:Object = new A.prototype.extend(); 
            var xml:XML = describeType(E);          
            trace(xml);

            O = copy(O, E, xml.method);
            O = copy(O, E, xml.variable);
            O = copy(O, E, xml.constant);
            O = copy(O, E, xml.accessor);

            O.prototype = { }; O.prototype.extend = E;
            return O;
            }
        else return new A(); //->
        }

    private function extend(A:Object, B:Object, b:Boolean = false):Object
        {
        var xml:XML = describeType(B);

        A.prototype.extend = B;
        A = copy(A, B, xml.constant);
        A = copy(A, B, xml.variable);
        A = copy(A, B, xml.method);
        A = copy(A, B, xml.accessor);

        return A;
        }

    private function copy(A:Object, B:Object, xml:XMLList):Object   
        {
        var node:XML

        for each(node in xml)
            {
            try { A[node.@name] = B[node.@name] } catch (e:Error) { trace('fail: '+node.@name) };
            }

        return A;
        }


    }

}


{

public dynamic class D
    {
    public static var abc:String = 'adsda';
    public const abd:String = '23223';
    private var width:Number;

    public function D() 
        {

        }

    public function toString():String 
        {
        return 'object';
        }   


    }

}

now its working. The last post was someWHAT shameful for some part of the bananas.
thats why i dropped another letter. for the accessors i had to go the long way. oldschool javascript...

package
{
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.events.Event;
import flash.utils.getDefinitionByName;
import flash.utils.getQualifiedClassName;
import flash.utils.describeType;

public class Main extends Sprite 
    {

    public function Main():void 
        {
        if (stage) init();
        else addEventListener(Event.ADDED_TO_STAGE, init);
        }

    private function init(e:Event = null):void 
        {
        removeEventListener(Event.ADDED_TO_STAGE, init);

        var C:Class = Class(extend(D, Sprite));
        var O:Object = _new(C);

        var s:Sprite = new Sprite();
        O.addEventListener('asddas',event);
        O.dispatchEvent(new Event('asddas'));
        O.addChild(s);

        O.graphics.clear();
        O.graphics.beginFill(0x000000,1);
        O.graphics.lineStyle(1, 0x000000, 1, true, "none"); 
        O.graphics.drawRect(0, 0, 100, 100);
        O.graphics.endFill();       

        trace(O.getChildAt(0), O.numChildren, O.width, O.prototype.extend.width, O.hasEventListener('asddas'), O.willTrigger('asddas'), O.mouseY, O.mouseEnabled);

        addChild(O.prototype.extend);
        }   


    private function event(e:Object):void
        {
        trace(e.type);
        }

    private function _new(A:Class):Object
        {
        if (A.prototype.extend)
            {
            var O:Object = new A();
            var E:Object = new A.prototype.extend(); 
            var xml:XML = describeType(E);          
            trace(xml);

            O = copy(O, E, xml.method);
            O = copy(O, E, xml.variable);
            O = copy(O, E, xml.constant);
            O = copy(O, E, xml.accessor);

            O.prototype = { }; O.prototype.extend = E;
            return O;
            }
        else return new A(); //->
        }

    private function extend(A:Object, B:Object, b:Boolean = false):Object
        {
        var xml:XML = describeType(B);

        A.prototype.extend = B;
        A = copy(A, B, xml.constant);
        A = copy(A, B, xml.variable);
        A = copy(A, B, xml.method);
        A = copy(A, B, xml.accessor);

        return A;
        }

    private function copy(A:Object, B:Object, xml:XMLList):Object   
        {
        var node:XML

        for each(node in xml)
            {
            try { A[node.@name] = B[node.@name] } catch (e:Error) { trace('fail: '+node.@name) };
            }

        return A;
        }


    }

}

package
{

public dynamic class D
    {
    public static var abc:String = 'adsda';
    public const abd:String = '23223';
    private var width:Number;

    public function D() 
        {

        }

    public function toString():String 
        {
        return 'object';
        }   


    }

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文