如何在ActionScript 3中从类的实例获取一个Class对象?

46

如何从一个actionscript类的实例中获取Class

在Python中,可以使用x.__class__;在Java中,可以使用x.getClass();

我知道有某些可怕的黑科技可以做到这一点,但我正在寻找一种内置的语言功能,或者至少是基于可靠东西构建的库程序。

3个回答

69
您可以通过基础Object类的“constructor”属性获取它。例如:
var myClass:Class = Object(myObj).constructor;

据我所知,这是我的独立宝石,尽管Adobe文档中的Object类提到了构造函数属性及其含义。但我从未在其他任何地方看到过它被使用。 - Gerald
1
这里有更多讨论:http://joshblog.net/2009/05/11/retrieve-the-class-used-to-instantiate-an-object-in-as3/稍微有一个替代方案是这样做的:var classRef:Class = myObj["constructor"] as Class;这也可以避免严格的编译器检查。不确定哪个性能更好。迈克·钱伯斯 - mikechambers
6
这不适用于继承Proxy类的对象,比如XML。请参考这篇回答 - https://dev59.com/IUbRa4cB1Zd3GeqPzFBe#472300 - Richard Szalay
这真的很好。巧妙地避免了我在引用主舞台上的类时遇到的问题。非常感谢! - Glitcher

14
接受(目前最受欢迎的答案)存在一些缺陷。该答案适用于特定情况,但评论已将其扩展为似乎是通用解决方案。
然而,在某些情况下,它不是类型安全的解决方案,也没有涵盖所有可能的对象。XML不受支持的想法在这里和其他地方得到了很好的解决,但类型安全的想法却没有。
假设是由程序员创建的类对象。以下是我设置的一些测试(这是在严格模式下,但是一个本地测试)。请注意int测试结果:
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("...");

假设有以下定义的TestClass:

package
{
    public class TestClass
    {
    }
}

结果:

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]
...

在目前的测试之外,有足够的理由使用 getDefinitionByName 方法,而不是constructor方法。 getDefinitionByName方法允许:

  • Adobe为(当前和未来的)问题领域开发内部解决方案
  • 您将无需更改代码以适应未来的Adobe开发
  • 您不必开发两个(或多个)动态实例化的分离方法。

现在可能会比较慢,但未来由Adobe推出的改进可能会解决速度问题。

例如,以前在for循环中,uint 要比int慢得多,因此设置了大量的转换代码以使用更快的int 。这是一个相当简单的问题,所以Adobe进行了修复,现在有很多代码需要跳过一些不必要的步骤来实现过时的目标。

由于getDefinitionByName方法在所有情况下都能正确工作,因此应该使用该方法编写代码,然后努力让Adobe解决速度问题。


14

您不能这样做的任何原因吗?

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]

我不知道避免通过字符串来回传递的方法,但这应该足够有效。


2
这个方法虽然可行,但 getQualifiedClassName 和 getDefinitionByName 的性能相当差。 - mikechambers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接