2010-04-10 17 views
5

He estado escribiendo un sistema que en tiempo de ejecución genera algunas plantillas, y luego genera algunos objetos basados ​​en esas plantillas. Tenía la idea de que las plantillas pueden ser extensiones de la clase clase, pero que resultó en unas magníficas errores:¿Es legal extender la clase Class?

VerifyError: Error #1107: The ABC data is corrupt, attempt to read out of bounds. 

Lo que me pregunto es si la clase de subclases es aún posible, si hay algún caso en el que tal vez hacer esto sería apropiado, y no solo un mal uso grosero de OOP. Creo que debería ser posible, ya que ActionScript le permite crear variables del tipo Clase. Este uso se describe en el LiveDocs entry for Class, sin embargo, no he visto menciones de clase subclase.

Aquí está un ejemplo de pseudocódigo:

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 

no tengo idea de lo que sería el tipo de b. ¿Sería esto?

trace(b is A); // true? 

Pero entonces, ¿podría escribir la variable b Para escribir A, como en var b:A = new A();, a pesar de que A no existe hasta el tiempo de ejecución? He leído que esto no es posible ya que A no se puede resolver de forma estática, pero estoy haciendo mis propias pruebas para explorar esta posibilidad.

En última instancia, el propósito es generar nuevas clases en tiempo de ejecución, y luego crear instancias de esas clases.

En resumen: ¿puede subclasificar la clase Class? De ser así, ¿cómo puede hacerlo sin errores, y qué tipo son las instancias de las instancias de la subclase Class?

+0

La pregunta principal es: ¿Es Clase una clase? –

+0

Bueno, en realidad estoy preguntando si puede subclasificar la clase Class, o si eso es un uso indebido del modelo de clase. Ya sé que Class es una clase; aquí está la clase Class livedoc: http://help.adobe.com/en_US/AS3LCR/Flash_10.0/Class.html – ivanreese

+0

a instanceof b // true –

Respuesta

1

Estas son las conclusiones de mi propia investigación en profundidad:

Ampliación de la clase Clase parece ser intrínsecamente imposible, aunque esto no está bien documentada en cualquier lugar que aún no he visto.A partir de mi investigación, ahora estoy convencido de que la clase Class no incluye todas las cualidades que tienen las otras clases de nivel superior, aunque se dice que todas ellas se extienden desde la clase Object.

Aún más frustrante es el hecho de que la subclasificación de diferentes clases de nivel superior dará lugar a varios mensajes de error diferentes, lo que hace que sea un tanto difícil saber qué problemas están en juego. Para empezar con un ejemplo sencillo, si se intenta subclase muchos de los tipos de datos primitivos de ActionScript (int, uint Número, cadena, booleano, etc.), se obtiene el siguiente compilador de error:

1016: Base class is final. 

Esto tiene sentido , porque mirando la documentación para cualquiera de estas clases revela que son de hecho final:

Package  Top Level 
Class   public final class Boolean 
Inheritance Boolean -> Object 

la palabra clave final, por supuesto, significa que otra clase no se puede extender la clase marcada como definitiva. Ahora, para un ejemplo más complicado, veamos una extensión de la clase de Función. La clase de función no es definitiva, de acuerdo con los documentos. Como no es final, ¿significa que podemos extender la clase de Función para crear nuestros propios objetos de función especializados ? Aquí es una definición:

class MyFunction extends Function { /*...*/ } 

.. y luego en el tiempo de ejecución :

VerifyError: Error #1103: Class ::MyFunction cannot extend final base class. 

comparar esto con el error tipo de datos primitivo anteriormente. Ese error ocurrió en el momento de la compilación, ya que la clase primitiva heredada se marcó como definitiva. La clase de función es no marcada como definitiva, pero la clase todavía se comporta como si fuera, solo en tiempo de ejecución.

Ahora, llegamos a la cuestión de la pregunta principal: ampliar la clase Class. Al igual que con la clase Function, la clase Class no es definitiva. Además, la clase Class es dinámica, lo que significa que se pueden agregar nuevas propiedades a un objeto Class en tiempo de ejecución.

Como una interesante nota al margen: La clase de función también es dinámica, y creo que esta parte de lo que permite el soporte continuo de los viejos mecanismos de herencia prototípica presentes en el dialecto ECMAscript. En este dialecto, las funciones se utilizan como clases de un tipo (bueno, prototipos), y la capacidad de las funciones para agregar propiedades en el tiempo de ejecución es parte del poder de la herencia prototípica.

Ahora, entiendo que las propiedades de un objeto Class son las mismas que las propiedades estáticas disponibles para cualquier instancia de esa clase. Por lo tanto, debe tener sentido lógico que alguien desee manipular un objeto Class en tiempo de ejecución, lo que le permite cambiar el comportamiento de esa clase y sus instancias. Que la clase Class sea dinámica refuerza esta noción.

Dado que la clase Class no es definitiva, tenía curiosidad por ver si se puede ampliar la clase Class, crear su propia especialización del modelo Class y trabajar en algún lugar del dominio meta-language. Dejaré para otro día la discusión de por qué alguien querría hacer esto, y qué poder hipotéticamente permitiría. Ahora, para el ejemplo final, extendamos la clase Class. Aquí hay una definición:

// 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 

..y luego en el tiempo de ejecución :

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

Santo StackTrace! El VerifyError está reservado para datos SWF malformados. En función de lo que pude encontrar, esta es también la forma en que un "error" en Flash Player tiende a manifestarse. En cualquier caso, esto va un poco más allá de un error común de ActionScript.

En este punto, se vuelve bastante difícil de entender exactamente lo que está sucediendo, pero esto es lo que he podido deducir hasta ahora.

VerifyError: Error #1107: The ABC data is corrupt, attempt to read out of bounds. 

I (por error, ver más abajo comentario) creen que "ABC" es sinónimo de clase base abstracta, que es un término que se aplica a las clases que no se pueden crear instancias, sólo se extendió. Sin embargo, el error aterrador anterior no viene en un momento de creación de instancias, sino en el primer acceso de la clase de clase MyClass. De hecho, el código del ejemplo, nunca una vez instanciar un objeto MyClass, solo me refiero a la clase MyClass.

Hice algunas pruebas más y descubrí que los objetos de clase no parecen tener constructores, al menos, del tipo que normalmente provienen de las subclases de objeto. Simplemente escribiendo new Class(); en cualquier parte de su código demostrará muy bien este hecho, pero puede investigar esto más a fondo inspeccionando la propiedad .constructor y con otros trucos. Como resultado de esto, las instancias de la clase Class son, en el mejor de los casos, objetos de segunda clase, ya que no se pueden construir en tiempo de ejecución.

Al principio sospeché que esta era la causa exacta de mi desagradable VerifyError. Sin embargo, ahora creo que hay muchos otros elementos en una clase, invisibles para nuestro código ActionScript, que pueden existir o no dentro de la clase Class, la clase Function u otros lugares curiosos. Ciertamente, cuando Flash Player intenta acceder a uno de los necesarios para la extensión de una clase base, y no existe (ya que Class es posiblemente un ABC, por lo que faltan ciertos elementos presentes en una clase normal), uno podría esperar para ver un fuera de límites VerifyError.

En resumen, la ampliación de la clase Class parece ser imposible en este momento. Parece que la clase Class no incluye todas las cualidades que la mayoría de las otras clases de nivel superior heredan de Object, aunque esto es difícil de probar.

Preferiría ver un resultado de mensaje de error más específico al extender Class, pero por el momento no existe tal cosa. Me encantaría ver que alguna capacidad de metaprogramación regrese a ActionScript. Por ahora, es suficiente saber de manera concluyente que no se puede hacer, al menos, de esta manera.

+0

ABC en este caso significa código de bytes de ActionScript. El seguimiento que ha publicado es el ABC que se está ejecutando cuando se lanza la excepción, siendo la última línea el código de operación de "nueva clase". Si revisa los documentos de AVM para newclass (http://www.adobe.com/devnet/actionscript/articles/avm2overview.pdf), verá que las clases base (en este caso, clase y objeto) deben estar en la pila y se ejecutarán sus inicializadores estáticos. Quizás esta es la raíz de la excepción: Class no tiene un inicializador estático, y buscarlo genera una lectura fuera de límites. – tclem

+0

tclem, gracias por el enlace. No tenía idea de que proporcionaran ese documento. Lo leeré y revisaré mi publicación con lo que aprendo. – ivanreese

5

Del livedoc en el primer párrafo indica Every Class object is an instance of the Class class. Por lo tanto, sería un error extender Class como cualquier objeto de clase que ya sea una clase.

Dijiste a system that generates some templates, and then generates some objects based on those templates. Parece que lo que realmente intentas hacer es crear una interfaz.

Se debe utilizar una interfaz cuando su plantilla no proporciona ninguna implementación. Es decir, declaras un conjunto de campos y métodos, pero no proporcionas ninguna implementación de los métodos. Se podría declarar una clase como sigue:

public interface Foo { 
    function bar:void; 
} 

ahora para crear una clase que implementa esta interfaz sólo tiene que hacer lo siguiente.

public class MyClass implements Foo { 
    function bar:void { 
     ..... implementation goes here ..... 
    } 
} 

Es posible que una clase implemente interfaces múltiples, mientras que puede extender solo una clase.

Sin embargo, si desea proporcionar cualquier implementación en su clase de plantilla, es probable que sea mejor que solo cree una clase que tenga las características comunes que tienen sus subclases y solo use la antigua herencia simple.

Espero que esto ayude.

+0

Matt, gracias por tu respuesta. Voy a aclarar la pregunta un poco más, ya que ha cubierto el problema como lo presenté bastante bien, pero me doy cuenta ahora que no especifiqué por completo el uso que tengo en mente. Las interfaces no funcionarán en este caso, ya que una interfaz en Actionscript no es un objeto per se (aunque es un tipo de datos, de acuerdo con los documentos), es una construcción utilizada para estandarizar la interfaz pública de una clase. Lo que estoy buscando es una representación de objetos de una clase que pueda ser manipulada e instanciada dinámicamente en tiempo de ejecución. – ivanreese

+0

También, re: su primer párrafo: ¿por qué sería un error? No veo eso, aunque parece que lo estoy experimentando (ver: Error de ABC). Si cada objeto de tipo Class es una instancia de la clase Class, ¿por qué no puedo crear una subclase de la clase Class y luego crear instancias de la subclase, ya que seguirán teniendo la clase Class en su ascendencia? – ivanreese

+0

Por último, votaré su respuesta tan pronto como tenga 15 rep. Como esta es mi primera pregunta, y hoy es mi primer día publicando activamente en el sitio (aunque he sido fan y lector por mucho tiempo), me tomará un poco antes de llegar a bordo. y capaz de participar completamente Una vez más, gracias. – ivanreese

Cuestiones relacionadas