是否可以在Action Script 3中动态创建用户定义的Class实例?

时间:2011-01-12 15:23:40

标签: actionscript-3 runtime classloader factory

我有一个工厂,其中Action Script跟随xml并构建了DisplayObject层次结构。这意味着脚本事先不知道它将在xml中遇到哪些元素,因此不知道它将需要哪些用户定义的工厂类。

我知道可以这样做:

var rect:*, className:String = "flash.geom.Rectangle";

if (ApplicationDomain.currentDomain.hasDefinition(className)) {         
    rect = new(getDefinitionByName(className));
}

Rectangle 实例将被实例化。但是一旦我用用户定义的东西替换 flash.geom.Rectangle ,比如 my.factory.Block 就会停止工作,如果我注释掉条件,我会变得简单: “未定义变量块”错误。

明显的解决方法是在激活工厂之前创建 my.factory.Block (以及所有其他组件)的实例,但这样做会破坏动态组件工厂的整个点。

当然我有:导入脚本顶部的my.factory。*; 语句。

有没有更智能的解决方案?

5 个答案:

答案 0 :(得分:3)

正如其他人所指出的那样,问题很可能是那些没有包含在已编译的swf中的类。正如丹尼尔指出的那样,导入是不够的,你需要引用这个类。但是,您不需要声明变量,如Cay所述,您可以执行以下操作:

MyClass的;

但是,如果您正在使用mxmlc进行编译,则可以使用-includes选项指定要强制包含在已编译的swf中的类或类。关于这一点的好处是它不需要你在代码中有一个引用。它看起来像这样:

-includes com.example.MyClass com.example.MyOtherClass

如果你想要包含一个非常大的类包,但不想为每个类写出类名,你可以使用compc将包编译为swc,并使用 - mxmlc的include-libraries选项包括整个包。

答案 1 :(得分:2)

我从来没有使用ApplicationDomain.currentDomain.hasDefinition(className),相反,我一直在尝试使用try catch方法,但看起来这是更好的方法。所以,谢谢你。

反正

我之前遇到过(我认为)同样的问题。问题是编译器不会编译所有my.factory.*;资产。我所做的是为我需要的每个对象创建一个虚拟实例。

privete function uncalledFunction():void{
  var s_01:Block;
  var s_02:Triangle;
  var s_03:Pineapple;
}

这个“欺骗它”对我有用,但我很想知道是否有更优雅的解决方案。

答案 2 :(得分:2)

我做过类似Daniel的回复,但你甚至不需要声明变量......这就足够了:

Block; Triangle; Pineapple;

答案 3 :(得分:2)

其他人提供了解决方案,但这里是对正在发生的事情的解释。

编译时,import语句实际上不包含类代码。它基本上将类型签名带入范围,以便编译器不会barf。

来自http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/statements.html#import

  

如果导入类但未在脚本中使用它,则该类不会作为SWF文件的一部分导出。这意味着您可以导入大型包而无需担心SWF文件的大小;只有在实际使用该类时,与类关联的字节码才包含在SWF文件中。导入不需要的类的一个缺点是增加了名称冲突的可能性。

提供的解决方案提供了将类添加到SWF中的方法。

编辑:

好的,我想我更了解你原来的问题。类代码必须来自某个地方。它必须通过所提供的方法之一链接,或者您需要将类放入子SWF(s),并更新您的逻辑以获取类名,加载正确的子SWF,然后从中获取类定义刚刚加载的SWF的ApplicationDomain。

答案 4 :(得分:0)

以下是我刚刚汇总的一些代码。我在时间轴上尝试了它并且它有效。这是你想要的吗?

import flash.system.ApplicationDomain;

trace( makeInstance( "flash.display.Sprite" ) ); //[object Sprite]
trace( makeInstance( "flash.geom.Rectangle" ) ); //(x=0, y=0, w=0, h=0)
trace( makeInstance( "hi.there" ) ); //null

function makeInstance( className : String ) : *
{
    var MyClass:Class;
    var instance : * = null;

    if ( ! ApplicationDomain.currentDomain.hasDefinition( className ) ) return null;

    MyClass = getDefinitionByName( className ) as Class;
    return new MyClass();
}