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

发布于 2024-10-11 19:25:44 字数 670 浏览 8 评论 0原文

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

我知道可以做这样的事情:

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

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

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

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

当然,我在脚本顶部有: import my.factory.*; 语句。

有没有更聪明的解决方案?

I got a factory, where Action Script follows an xml and builds DisplayObject hierarchy out of it. It is meant that script doesn't know beforehand what elements it will encounter in xml and therefore doesn't know what user-defined factory classes it will need.

I know that it is possible to do something like this:

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

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

And Rectangle instance will get instantiated. But as soon as I replace flash.geom.Rectangle with something user-defined, like my.factory.Block it stops working and if I comment out conditional I get simple: "Variable Block is not defined" error.

Obvious workaround would be to create an instance of my.factory.Block (and all other components), prior to activating the factory, but that kinda ruins whole point of dynamic component factory.

Of course I have: import my.factory.*; statement at the top of the script.

Is there any smarter solution to this?

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

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

发布评论

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

评论(5

单挑你×的.吻 2024-10-18 19:25:45

正如其他人指出的那样,问题很可能是类未包含在编译的 swf 中。正如丹尼尔指出的那样,导入是不够的,您需要对该类的引用。但是,您不需要声明变量,正如 Cay 所说,您只需执行以下操作即可:

MyClass;

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

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

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

As others have pointed out, the problem is most probably that of classes not being included in the compiled swf. As Daniel pointed out, an import is not enough, you need a reference to the class. You don't, however, need to declare a variable, as Cay stated, you can just do as follows:

MyClass;

Although, if you're using the mxmlc to compile, you can use the -includes option to specify a class, or classes, that you would like to force to be included in the compiled swf. The nice thing about this is it doesn't require you to have a reference in your code. It looks like this:

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

If you have a really big package of classes you want to include, but don't want to write out the class name for every class, you can compile the package as a swc, using the compc, and the use the -include-libraries option of mxmlc to include the entire package.

十秒萌定你 2024-10-18 19:25:45

我从未使用过 ApplicationDomain.currentDomain.hasDefinition(className),而是一直使用 try catch 方法来执行此操作,但看起来这是更好的方法。所以谢谢你。

不管怎样,

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

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

这种“欺骗”对我来说很有效,但我有兴趣看看是否有更优雅的解决方案。

i've never used ApplicationDomain.currentDomain.hasDefinition(className), instead I've been using the try catch way of doing this, but looks like this is the better way of doing this. so thanks for that.

anyway,

I've come across (i think) this same issue before. The problem is that the compiler doesn't compile all your my.factory.*; assets. What I have done is created a dummy instance of each object I will require.

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

This "tricking it" has worked for me, but I'm interested to see if there are any more elegant solutions.

生生不灭 2024-10-18 19:25:45

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

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

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

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

所提供的解决方案提供了将类放入 SWF 的方法。

编辑:

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

Others have offered solutions, but here is an explanation of what is happening.

The import statement does not actually include the class code when you compile. It basically brings the type signature(s) into scope so that the compiler doesn't barf.

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

If you import a class but do not use it in your script, the class is not exported as part of the SWF file. This means you can import large packages without being concerned about the size of the SWF file; the bytecode associated with a class is included in a SWF file only if that class is actually used. One disadvantage of importing classes that you do not need is that you increase the likelihood of name collisions.

The solutions presented provide methods for getting the classes into the SWF.

Edit:

OK, I think I better understand your original question. The class code has to come from somewhere. It either has to be linked in via one of the methods presented, or you need to put the classes into children SWF(s), and update your logic to get the class name, load the proper child SWF, then get the class definition from the ApplicationDomain of the SWF you just loaded.

烟沫凡尘 2024-10-18 19:25:45

我做了一些类似于丹尼尔的回应,但你甚至不需要声明变量......这样就足够了:

Block; Triangle; Pineapple;

I've done something similar to Daniel's response, but you don't even need to declare variables... it's enough with this:

Block; Triangle; Pineapple;
又爬满兰若 2024-10-18 19:25:45

这是我刚刚拼凑在一起的一些代码。我在时间轴上尝试过,它有效。是你想要的吗?

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();
}

Here's some code that I just threw together. I tried it on the Timeline and it works. Is it what you want?

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