Domanda Come posso ottenere da un'istanza di una classe a un oggetto Class in ActionScript 3?


Come si ottiene un'istanza della classe ActionScript Class da un'istanza di quella classe?

In Python, questo sarebbe x.__class__; in Java, x.getClass();.

Lo sono consapevole alcuni terribili hack esiste per fare questo, ma sto cercando una funzione di linguaggio integrata, o almeno una routine di libreria costruita su qualcosa di affidabile.


44
2017-10-15 07:51


origine


risposte:


Puoi ottenerlo attraverso la proprietà 'constructor' della classe Object di base. vale a dire .:

var myClass:Class = Object(myObj).constructor;

69
2017-10-15 08:19



Qualche ragione per cui non potresti farlo?

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]

Non conosco un modo per evitare di inciampare attraverso una stringa, ma dovrebbe funzionare abbastanza bene.


14
2017-10-15 08:18



La risposta accettata (e attualmente più popolare) ha alcuni difetti. La risposta serve per questo specifico caso d'uso, ma i commenti hanno ampliato la risposta a una apparente soluzione generale.

Ma in alcuni casi non è una soluzione sicura per il tipo e non affronta tutti gli oggetti possibili. L'idea che XML non è supportato è stata affrontata abbastanza bene qui e altrove, ma l'idea di sicurezza del tipo non ha.

L'assunto è che si tratta di un oggetto di classe creato dal programmatore. Ecco alcuni test che ho impostato (questo è in modalità rigorosa, ma un test locale). Notare la int risultati del test:

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 definito come:

package
{
    public class TestClass
    {
    }
}

risultati:

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]
...

Al di là di qualsiasi test corrente, vi è ragione abbastanza buona da usare getDefinitionByName sopra il constructor metodi. Il getDefinitionByName il metodo consente:

  • Adobe per sviluppare soluzioni interne per le aree problematiche (attuali e future)
  • non dovresti cambiare il tuo codice per i futuri sviluppi di Adobe
  • non è necessario sviluppare due (o più) metodi separati di istanziazione dinamica.

Potrebbe essere più lento ora, ma in futuro potrebbero esserci dei miglioramenti da parte di Adobe che potrebbero risolvere il problema della velocità.

(Ad esempio, era così uint era molto più lento a "for-loops" di int, quindi è stato impostato un sacco di codice di conversione per utilizzare il più veloce int. È stato un problema abbastanza semplice da risolvere, quindi Adobe l'ha risolto, e ora c'è un sacco di codice che salta attraverso alcuni inutili cerchi per raggiungere un obiettivo superato.)

Dal momento che il getDefinitionByName il metodo funziona correttamente in tutti i casi, il codice dovrebbe essere sviluppato utilizzando tale metodo e quindi lavorare per ottenere Adobe per risolvere il problema di velocità.


14
2018-02-05 20:35