flex - que - ¿Cómo puedo acceder desde una instancia de una clase a un objeto Class en ActionScript 3?
que es un objeto en programacion (3)
¿Cómo se obtiene una instancia de la clase de Class
actionscript a partir de una instancia de esa clase?
En Python, esto sería x.__class__
; en Java, x.getClass();
.
Soy consciente de que existen ciertos hacks terribles para hacer esto, pero estoy buscando una instalación de lenguaje integrada, o al menos una rutina de biblioteca basada en algo confiable.
¿Alguna razón por la que no pudiste hacer esto?
var s:Sprite = new flash.display.Sprite();
var className:String = flash.utils.getQualifiedClassName( s );
var myClass:Class = flash.utils.getDefinitionByName( className ) as Class;
trace(className ); // flash.display::Sprite
trace(myClass); // [class Sprite]
var s2 = new myClass();
trace(s2); // [object Sprite]
No sé cómo evitar un disparo circular a través de un String, pero debería funcionar bastante bien.
La respuesta aceptada (y actualmente más popular) tiene algunos defectos. La respuesta sirve para este caso de uso específico, pero los comentarios han ampliado la respuesta a una aparente solución general.
Pero no es una solución segura en ciertos casos, y no aborda todos los objetos posibles. La idea de que XML no es compatible se ha abordado suficientemente bien aquí y en otros lugares, pero la idea de tipo seguro no.
La suposición hecha es que es un objeto de clase creado por el programador. Aquí hay algunas pruebas que configuré (esto es en modo estricto, pero una prueba local). Tenga en cuenta los resultados de la prueba int
:
var sprite:Sprite = new Sprite();
var xml:XML = new XML();
var testInt:int = 2;
var testClass:TestClass = new TestClass();
var testAnon:Object = {};
trace("classname 1 = " + getQualifiedClassName(sprite));
trace("myclass 1 = " + getDefinitionByName(getQualifiedClassName(sprite)));
trace("constructor a 1 = " + Object(sprite).constructor);
trace("constructor a 1 = " + (Object(sprite).constructor as Class));
trace("constructor b 1 = " + sprite["constructor"]);
trace("constructor b 1 = " + (sprite["constructor"] as Class));
trace("...");
trace("classname 2 = " + getQualifiedClassName(xml));
trace("myclass 2 = " + getDefinitionByName(getQualifiedClassName(xml)));
trace("constructor a 2 = " + Object(xml).constructor);
trace("constructor a 2 = " + (Object(xml).constructor as Class));
trace("constructor b 2 = " + xml["constructor"]);
trace("constructor b 2 = " + (xml["constructor"] as Class));
trace("...");
trace("classname 3 = " + getQualifiedClassName(testInt));
trace("myclass 3 = " + getDefinitionByName(getQualifiedClassName(testInt)));
trace("constructor a 3 = " + Object(testInt).constructor);
trace("constructor a 3 = " + (Object(testInt).constructor as Class));
trace("constructor b 3 = " + testInt["constructor"]);
trace("constructor b 3 = " + (testInt["constructor"] as Class));
trace("...");
trace("classname 4 = " + getQualifiedClassName(testClass));
trace("myclass 4 = " + getDefinitionByName(getQualifiedClassName(testClass)));
trace("constructor a 4 = " + Object(testClass).constructor);
trace("constructor a 4 = " + (Object(testClass).constructor as Class));
trace("constructor b 4 = " + testClass["constructor"]);
trace("constructor b 4 = " + (testClass["constructor"] as Class));
trace("...");
trace("classname 5 = " + getQualifiedClassName(testAnon));
trace("myclass 5 = " + getDefinitionByName(getQualifiedClassName(testAnon)));
trace("constructor a 5 = " + Object(testAnon).constructor);
trace("constructor a 5 = " + (Object(testAnon).constructor as Class));
trace("constructor b 5 = " + testAnon["constructor"]);
trace("constructor b 5 = " + (testAnon["constructor"] as Class));
trace("...");
Con TestClass
definido como:
package
{
public class TestClass
{
}
}
Resultados:
classname 1 = flash.display::Sprite
myclass 1 = [class Sprite]
constructor a 1 = [class Sprite]
constructor a 1 = [class Sprite]
constructor b 1 = [class Sprite]
constructor b 1 = [class Sprite]
...
classname 2 = XML
myclass 2 = [class XML]
constructor a 2 =
constructor a 2 = null
constructor b 2 =
constructor b 2 = null
...
classname 3 = int
myclass 3 = [class int]
constructor a 3 = [class Number]
constructor a 3 = [class Number]
constructor b 3 = [class Number]
constructor b 3 = [class Number]
...
classname 4 = src::TestClass
myclass 4 = [class TestClass]
constructor a 4 = [class TestClass]
constructor a 4 = [class TestClass]
constructor b 4 = [class TestClass]
constructor b 4 = [class TestClass]
...
classname 5 = Object
myclass 5 = [class Object]
constructor a 5 = [class Object]
constructor a 5 = [class Object]
constructor b 5 = [class Object]
constructor b 5 = [class Object]
...
Más allá de cualquier prueba actual, existe una buena razón para usar getDefinitionByName
sobre los métodos de constructor
. El método getDefinitionByName
permite:
- Adobe para desarrollar soluciones internas para las áreas problemáticas (actuales y futuras)
- no tendría que cambiar su código para futuros desarrollos de Adobe
- no tiene que desarrollar dos (o más) métodos separados de creación de instancias dinámicas.
Puede ser más lento ahora, pero en el futuro puede haber mejoras desde el lado de Adobe que abordarían el problema de la velocidad.
(Por ejemplo, solía ser que uint
era mucho más lento en for-loops que int
, por lo que se configuró una gran cantidad de código de conversión para usar el int
más rápido. Fue un problema bastante simple de resolver, por lo que Adobe lo solucionó, y ahora hay un montón de código que salta a través de algunos aros innecesarios para lograr un objetivo obsoleto).
Dado que el método getDefinitionByName
funciona correctamente en todos los casos, el código debe desarrollarse con ese método y luego trabajar para que Adobe solucione el problema de la velocidad.
Puede obtenerlo a través de la propiedad ''constructor'' de la clase de objeto base. es decir:
var myClass:Class = Object(myObj).constructor;