iva*_*ese 5 oop flash metaprogramming actionscript-3
我一直在编写一个系统,在运行时生成一些模板,然后根据这些模板生成一些对象.我有一个想法,模板可能是Class类的扩展,但这导致了一些宏伟的错误:
VerifyError: Error #1107: The ABC data is corrupt, attempt to read out of bounds.
Run Code Online (Sandbox Code Playgroud)
我想知道的是,如果子类化Class甚至可能,如果有可能在某些情况下这样做是合适的,而不仅仅是对OOP的严重滥用.我相信它应该是可能的,因为ActionScript允许您创建Class类型的变量.这个用法在Class的LiveDocs条目中描述,但我没有看到子类化Class的提及.
这是一个伪代码示例:
class Foo extends Class
var A:Foo = new Foo(); // A is a class
trace(A is Class); // true, right?
var b = new A(); // b is an instance of class A
Run Code Online (Sandbox Code Playgroud)
我不知道b会是什么类型.会这样吗?
trace(b is A); // true?
Run Code Online (Sandbox Code Playgroud)
但后来,你能输入变量b输入A,如var b:A = new A();,即使A不存在,直到运行?我已经读过,这是不可能的,因为A不是静态可解析的,但我正在进行自己的测试来探索这种可能性.
最终,目的是在运行时生成新类,然后创建这些类的实例.
总结:你可以继承Class类吗?如果是这样,你怎么能没有错误地做到这一点,以及Class子类实例的实例是什么类型的?
从第一段中的livedoc开始,它声明Every Class object is an instance of the Class class.,因为任何类对象已经是一个类,所以扩展Class会是一个错误.
你说a system that generates some templates, and then generates some objects based on those templates.这听起来像你真正想做的是创建一个界面.
当您的模板未提供任何实现时,应使用接口.也就是说,您声明了一堆字段和方法,但没有提供方法的实现.您可以按如下方式声明这样的类:
public interface Foo {
function bar:void;
}
Run Code Online (Sandbox Code Playgroud)
现在创建一个实现此接口的类,您只需执行以下操作.
public class MyClass implements Foo {
function bar:void {
..... implementation goes here .....
}
}
Run Code Online (Sandbox Code Playgroud)
类可以实现多个接口,而它可以只扩展一个类.
但是,如果您希望在模板类中提供任何实现,那么您最好只创建一个与其子类具有任何共性的类,并且只使用普通的旧继承.
希望这可以帮助.
以下是我自己深入研究的结果:
扩展 Class 类本质上似乎是不可能的,尽管这在我见过的任何地方都没有很好的记录。根据我的调查,我现在确信 Class 类本身并不包含其他顶级类所具有的所有品质,尽管据说它们都是从 Object 类扩展而来的。
更令人沮丧的是,子类化不同的顶级类将导致几种不同的错误消息,使得很难判断到底是什么问题。首先看一个简单的示例,如果您尝试对 ActionScript 的许多原始数据类型(int、uint、Number、String、Boolean 等)进行子类化,则会出现以下编译器错误:
1016: Base class is final.
Run Code Online (Sandbox Code Playgroud)
这是有道理的,因为查看这些类的文档表明它们确实是最终的:
Package Top Level
Class public final class Boolean
Inheritance Boolean -> Object
Run Code Online (Sandbox Code Playgroud)
当然,final 关键字意味着另一个类不能扩展标记为final 的类。现在,对于更复杂的示例,让我们看一下 Function 类的扩展。根据文档,Function 类不是最终的。既然它不是最终的,这是否意味着我们可以扩展 Function 类来创建我们自己的专用函数对象?这是一个定义:
class MyFunction extends Function { /*...*/ }
Run Code Online (Sandbox Code Playgroud)
..然后在运行时:
VerifyError: Error #1103: Class ::MyFunction cannot extend final base class.
Run Code Online (Sandbox Code Playgroud)
将此与上面的原始数据类型错误进行比较。该错误发生在编译时,因为继承的原始类实际上被标记为final。Function 类没有被标记为 Final,但该类的行为仍然像它一样,只是在运行时。
现在,我们来到了主要问题:扩展 Class 类。与 Function 类一样,Class 类也不是最终的。此外,Class 类是动态的,这意味着可以在运行时向 Class 对象添加新属性。
有趣的是:Function 类也是动态的,我相信这部分内容允许继续支持 ECMAscript 方言中存在的旧原型继承机制。在这种方言中,函数被用作某种类(好吧,原型),并且函数在运行时添加属性的能力是原型继承的力量的一部分。
现在,我的理解是 Class 对象的属性与该类的任何实例可用的静态属性相同。因此,有人可能希望在运行时操作 Class 对象,从而允许他们更改该类及其实例的行为,这应该是合乎逻辑的。Class 类是动态的强化了这一概念。
由于 Class 类不是最终的,我很好奇是否可以扩展 Class 类,以创建自己的 Class 模型专业化并在元语言领域的某个地方工作。我将留到另一天讨论为什么有人想要这样做,以及假设它会允许什么权力。现在作为最后的示例,让我们扩展 Class 类。这是一个定义:
// the definition causes no errors on its own, even though the compiler "sees" it
class MyClass extends Class { /*...*/ }
/* elsewhere */
MyClass; // the only mention of MyClass beyond the definition
Run Code Online (Sandbox Code Playgroud)
..然后在运行时:
verify global$init()
stack:
scope:
locals: global
/* snip about 120 lines */
46:getlex 34
stack: global Class$?
scope: global Object$ Class$
locals: global
48:newclass MyClass$cinit()
VerifyError: Error #1107: The ABC data is corrupt, attempt to read out of bounds.
at global$init()
Run Code Online (Sandbox Code Playgroud)
神圣的堆栈跟踪!是VerifyError为格式错误的 SWF 数据保留的。根据我所发现的情况,这也是 Flash Player 中“错误”的表现形式。无论哪种情况,这都稍微超出了普通的 ActionScript 错误范围。
此时,要准确理解正在发生的事情变得相当困难,但这是我迄今为止所能推断出的。
VerifyError: Error #1107: The ABC data is corrupt, attempt to read out of bounds.
Run Code Online (Sandbox Code Playgroud)
我(错误地,请参阅下面的评论)认为“ABC”代表抽象基类,该术语适用于无法实例化而只能扩展的类。然而,上述可怕的错误不是在实例化时出现的,而是在第一次访问 MyClass Class 子类时出现的。事实上,在示例的代码中,我从未实例化过 MyClass 对象,我只引用了 MyClass 类本身。
我做了一些进一步的测试,发现 Class 对象似乎没有构造函数,至少没有通常来自 Object 子类的构造函数。只需new Class();在代码中的任意位置键入即可很好地证明这一事实,但您可以通过检查.constructor属性和其他技巧来进一步研究这一点。因此,Class 类的实例充其量只是二类对象,因为它们无法在运行时构造。
起初我怀疑这就是我讨厌的真正原因VerifyError。然而,我现在相信类还有许多其他元素,这些元素对于我们自己的 ActionScript 代码来说是不可见的,它们可能存在于 Class 类、Function 类或其他奇怪的地方,也可能不存在。当然,当 Flash Player 尝试访问扩展基类所需的元素之一时,它并不存在(因为 Class 可能是 ABC,因此缺少普通类中存在的某些元素),人们很可能会期望看到出界了VerifyError。
综上所述,扩展 Class 类此时看起来是不可能的。看起来 Class 类并不包含大多数其他顶级类从 Object 继承的所有品质,尽管这很难测试。
我希望看到扩展类产生更具体的错误消息,但目前还没有这样的东西。我希望看到 ActionScript 中回归一些元编程功能。现在,只要能够确定地知道这件事至少不能以这种方式完成就足够了。