How do I get from an instance of a class to a Class object in ActionScript 3?

后端 未结 3 1724
感情败类
感情败类 2021-01-30 08:39

How do you get an instance of the actionscript class Class from an instance of that class?

In Python, this would be x.__class__; in Java,

相关标签:
3条回答
  • 2021-01-30 09:13

    You can get it through the 'constructor' property of the base Object class. i.e.:

    var myClass:Class = Object(myObj).constructor;
    
    0 讨论(0)
  • 2021-01-30 09:35

    The accepted (and currently most popular answer) has some flaws. The answer serves for this specific use case, but the comments have expanded the answer to a seeming general solution.

    But it is not a type-safe solution in certain cases, and it doesn't address all possible objects. The idea that XML is not supported has been addressed well enough here and elsewhere, but the type-safe idea has not.

    The assumption made is that it is an class object created by the programmer. Here are some tests that I set up (this is in strict mode, but a local test). Note the int test results:

    var sprite:Sprite = new Sprite();
    var xml:XML = new XML();
    var testInt:int = 2;
    var testClass:TestClass = new TestClass();
    var testAnon:Object = {};
    
    trace("classname 1 = " + getQualifiedClassName(sprite));
    trace("myclass 1 = " + getDefinitionByName(getQualifiedClassName(sprite)));
    trace("constructor a 1 = " + Object(sprite).constructor);
    trace("constructor a 1 = " + (Object(sprite).constructor as Class));
    trace("constructor b 1 = " + sprite["constructor"]);
    trace("constructor b 1 = " + (sprite["constructor"] as Class));
    trace("...");
    trace("classname 2 = " + getQualifiedClassName(xml));
    trace("myclass 2 = " + getDefinitionByName(getQualifiedClassName(xml)));
    trace("constructor a 2 = " + Object(xml).constructor);
    trace("constructor a 2 = " + (Object(xml).constructor as Class));
    trace("constructor b 2 = " + xml["constructor"]);
    trace("constructor b 2 = " + (xml["constructor"] as Class));
    trace("...");
    trace("classname 3 = " + getQualifiedClassName(testInt));
    trace("myclass 3 = " + getDefinitionByName(getQualifiedClassName(testInt)));
    trace("constructor a 3 = " + Object(testInt).constructor);
    trace("constructor a 3 = " + (Object(testInt).constructor as Class));
    trace("constructor b 3 = " + testInt["constructor"]);
    trace("constructor b 3 = " + (testInt["constructor"] as Class));
    trace("...");
    trace("classname 4 = " + getQualifiedClassName(testClass));
    trace("myclass 4 = " + getDefinitionByName(getQualifiedClassName(testClass)));
    trace("constructor a 4 = " + Object(testClass).constructor);
    trace("constructor a 4 = " + (Object(testClass).constructor as Class));
    trace("constructor b 4 = " + testClass["constructor"]);
    trace("constructor b 4 = " + (testClass["constructor"] as Class));
    trace("...");
    trace("classname 5 = " + getQualifiedClassName(testAnon));
    trace("myclass 5 = " + getDefinitionByName(getQualifiedClassName(testAnon)));
    trace("constructor a 5 = " + Object(testAnon).constructor);
    trace("constructor a 5 = " + (Object(testAnon).constructor as Class));
    trace("constructor b 5 = " + testAnon["constructor"]);
    trace("constructor b 5 = " + (testAnon["constructor"] as Class));
    trace("...");
    

    With TestClass defined as:

    package
    {
        public class TestClass
        {
        }
    }
    

    Results:

    classname 1 = flash.display::Sprite
    myclass 1 = [class Sprite]
    constructor a 1 = [class Sprite]
    constructor a 1 = [class Sprite]
    constructor b 1 = [class Sprite]
    constructor b 1 = [class Sprite]
    ...
    classname 2 = XML
    myclass 2 = [class XML]
    constructor a 2 = 
    constructor a 2 = null
    constructor b 2 = 
    constructor b 2 = null
    ...
    classname 3 = int
    myclass 3 = [class int]
    constructor a 3 = [class Number]
    constructor a 3 = [class Number]
    constructor b 3 = [class Number]
    constructor b 3 = [class Number]
    ...
    classname 4 = src::TestClass
    myclass 4 = [class TestClass]
    constructor a 4 = [class TestClass]
    constructor a 4 = [class TestClass]
    constructor b 4 = [class TestClass]
    constructor b 4 = [class TestClass]
    ...
    classname 5 = Object
    myclass 5 = [class Object]
    constructor a 5 = [class Object]
    constructor a 5 = [class Object]
    constructor b 5 = [class Object]
    constructor b 5 = [class Object]
    ...
    

    Beyond any current testing, there is fairly good reason to use getDefinitionByName over the constructor methods. The getDefinitionByName method allows :

    • Adobe to develop internal solutions for the (current and future) problematic areas
    • you would not have to change your code for future Adobe developments
    • you do not have to develop two (or more) separate methods of dynamic instantiation.

    It may be slower now, but in the future there may be improvements from Adobe's side that would address the speed issue.

    (For example, it used to be that uint was far slower in for-loops than int, so a lot of conversion code was set up to use the faster int. It was a fairly simple issue to solve, so Adobe fixed it, and now there is a lot of code that jumps through some unnecessary hoops to achieve an outdated goal.)

    Since the getDefinitionByName method works correctly in all cases, code should be developed using that method, and then work to get Adobe to fix the speed issue.

    0 讨论(0)
  • 2021-01-30 09:38

    Any reason you couldn't do this?

    var s:Sprite = new flash.display.Sprite();
    
    var className:String = flash.utils.getQualifiedClassName( s );
    var myClass:Class = flash.utils.getDefinitionByName( className ) as Class;
    
    trace(className ); // flash.display::Sprite
    trace(myClass); // [class Sprite]
    
    var s2 = new myClass();
    trace(s2); // [object Sprite]
    

    I don't know a way to avoid round-tripping through a String, but it should work well enough.

    0 讨论(0)
提交回复
热议问题