扩展Class类是合法的吗?

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类型的变量.这个用法在ClassLiveDocs条目中描述,但我没有看到子类化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子类实例的实例是什么类型的?

Mat*_*att 5

从第一段中的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)

类可以实现多个接口,而它可以只扩展一个类.

但是,如果您希望在模板类中提供任何实现,那么您最好只创建一个与其子类具有任何共性的类,并且只使用普通的旧继承.

希望这可以帮助.


iva*_*ese 1

以下是我自己深入研究的结果:

扩展 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 中回归一些元编程功能。现在,只要能够确定地知道这件事至少不能以这种方式完成就足够了。