2009-06-15 10 views
18

Da quello che ho capito di ActionScript, ci sono due tipi di calchi:ActionScript: Esiste sempre una buona ragione per utilizzare il cast "come"?

var bar0:Bar = someObj as Bar; // "as" casting 
var bar1:Bar = Bar(someObj); // "class name" casting (for want of a better name) 

Inoltre, e per favore mi corregga se sbaglio qui, as fusione sarà o restituire un'istanza della classe o null, mentre Il cast di "nome classe" restituirà un'istanza della classe o genererà un'eccezione se il cast è impossibile - a parte questo, sono identici.

Tuttavia, il lancio di as sembra essere un'enorme violazione del principio di fail-fast-fail-early ... E ho difficoltà a immaginare una situazione in cui sarebbe preferibile utilizzare un cast as di un cast di nome classe (con, possibilmente, un instanceof gettato lì).

Quindi, la mia domanda è: in quali circostanze sarebbe preferibile utilizzare il casting as?

+0

Si noti che l'associazione tardiva, in generale, che è spesso utile, è in conflitto diretto con la tua interpretazione di FF. – dkretz

+0

Questo è vero, è anche inevitabile in ActionScript in quanto non vi è alcuna nozione di "generici", quindi le cose che si estraggono dai contenitori saranno non tipizzate. –

+0

(quindi è preferibile fallire su 'var foo: Foo = Foo (myArray [i])' piuttosto che ottenere un null e trattare con un NPX da qualche altra parte) –

risposta

12

È necessario utilizzare as per eseguire il cast in due scenari: il casting su un Date e il casting su un Array.

Per le date, una chiamata a Date(xxx) si comporta come nuova Date().toString().

Per gli array, una chiamata a Array(xxx) creerà un Array con un elemento: xxx.

Procedimento Class() colata ha dimostrato di essere più veloce di as colata, quindi potrebbe essere preferibile quando as questioni di efficienza (e quando non lavora con Date e Array).

import flash.utils.*; 

var d = Date(1); 

trace("'" + d, "'is type of: ",getQualifiedClassName(d)); 

var a:Array = Array(d); 

trace("'" + a, "' is type of: ", getQualifiedClassName(a)); 

    //OUTPUT 
     //'Mon Jun 15 12:12:14 GMT-0400 2009 'is type of: String 
     //'Mon Jun 15 12:12:14 GMT-0400 2009 ' is type of: Array 

    //COMPILER ERRORS/WARNINGS: 
     //Warning: 3575: Date(x) behaves the same as new Date().toString(). 
     //To cast a value to type Date use "x as Date" instead of Date(x). 
     //Warning: 1112: Array(x) behaves the same as new Array(x). 
     //To cast a value to type Array use the expression x as Array instead of Array(x). 

`

1

Utilizzare "come" con gli array.

var badArray:Array; 
badArray = Array(obj); 

Produrrà una matrice di lunghezza uno con l'array originale nel primo elemento. Se si usa 'as' come segue, si ottiene il risultato corretto.

var goodArray:Array; 
goodArray = obj as Array; 

In generale, 'come' è preferibile 'Classe()' in ActionScript come si comporta più come fusione in altre lingue.

+1

Quando si dice "altre lingue", quale stai pensando di ? So per certo che Java solleverà un'eccezione se proverai a eseguire un cast errato ... –

+0

Java convertirà correttamente un elenco se lo fai Elenco lista = (Lista ) obj; Nessuna eccezione, nessun problema. Array (obj) in AS, problema. – stevedbrown

26

ci sono un paio di punti in questa discussione degno di nota.

C'è una grande differenza nel modo in cui i due funzionano, Class() tenterà di eseguire il cast dell'oggetto nella classe specificata, ma in caso contrario (a volte, dipende dal tipo di dati) genera un errore di runtime. D'altra parte l'utilizzo di oggetto come Class preformerà prima un controllo di tipo, e se l'oggetto specificato non può essere gettato nella classe indicata, verrà invece restituito un valore nullo.

Questa è una differenza molto importante ed è uno strumento utile in fase di sviluppo. Ci permette di fare quanto segue:

var o:MyClass = myArray[i] as MyClass; 

if(o) 
{ 
    //do stuff 
} 

Penso che l'utilità di ciò sia abbastanza ovvia.

"as" è anche più coerente con il resto della lingua (ad esempio: "myObject is MyClass").

Il metodo MyClass() offre ulteriori vantaggi, quando si lavora con i tipi semplici dati (int, Number, uint, stringa) Alcuni esempi di questo sono:

var s:String = "89567"; 
var s2:String = "89 cat"; 
var n:Number = 1.9897; 

var i:int = int(s); // i is = 89567, cast works 
var i2:int = int(s2); //Can't convert so i2 is set to 0 
var i3:int = int(n); // i = 1 
var n2:Number = Number(s2); // fails, n2 = NaN 

//when used in equations you'll get very different results 
var result:int = int(n) * 10; //result is 10 
var result:int = n * 10; //result is 19.89700 
var result:int = int(s2) * 10; //result is 0 

trace(s2 as Number); //outputs null 
trace(s2 as int); //outputs null 
trace(Number(s2)); //outputs NaN 

Questo è un argomento buono e importante, come regola generale Io uso "as" quando lavoro con Objects e Cast() quando uso tipi di dati più semplici, ma è proprio come mi piace strutturare il mio codice.

+0

'as' potrebbe essere più coerente con la lingua, ma non è ancora più pericoloso? Grazie per la risposta - le complessità di casting int/string/numero sono buone da sapere. –

+0

Cosa ritieni più pericoloso? Ciò che è pericoloso non è la gestione corretta di tutte le situazioni, ma si tratta di un problema sviluppatore non di una lingua. In realtà ritengo che sia più sicuro (controllo del tipo) e incredibilmente utile, e può portare a un codice più pulito. var o: Classe = a [i] come Classe || nuova classe(); // ottimo per questo genere di cose –

+0

Per chiarire perché penso che sia più sicuro: ti permette di provare un cast di tipo senza rompere le cose se fallisce. –

0

Lo uso quando ho un oggetto ArrayCollection di oggetti e ho bisogno di enumerarli, oppure usare una funzione di selezione.

ad es.

var abc: mytype = mycollection.getItemAt (i) come mytype

+0

Ma perché usi 'as' su' var abc: MyType = MyType (mycollection.getItemAt (i)) '? L'uso di 'as' introduce la possibilità di un bug sottile se' mycollection' contiene qualcosa che non è un 'MyType' (vedere la regola fail-fast) –

+0

Io lo uso perché per me MyType (...) è mentalmente un il cast e "as MyType" sono mentalmente un alias, e non lo sto lanciando, ma piuttosto asserendo che è ciò che rende felice il compilatore (anche se potrebbe essere lo stesso in questo caso). Ma io sono nella parte a forma di campana della curva a forma di campana, quindi probabilmente è soprattutto una riflessione su come penso al codice - preferisco che sia chiaro e semplice che si abbottoni in tutti gli angoli. Sono felice che abbiano lasciato javascript abbastanza bene da solo, piuttosto che farne un actioncript. Uso anche il costrutto "if (! Object) {}" menzionato in un'altra risposta un bel po '. – dkretz

5

Essi effettivamente fare cose diverse ... quando si dice

myvar as ClassName 

Si sono davvero solo lasciando che il compilatore sa che questo oggetto o è un ClassName o di una sottoclasse di ClassName

quando dici:

ClassName(myvar) 

Cerca effettivamente di convertirlo in quel tipo di oggetto.

quindi se il vostro oggetto è un o di una discesa della classe e non c'è bisogno di convertirlo si usa come

esempi:

var myvar:String = '<data/>'; 
var othervar:XML = XML(myvar); //right 

var myvar:String = '<data/>'; 
var othervar:XML = (myvar as XML); //wrong 

var myvar:XML = <data/>; 
var othervar:XML = myvar as XML; // right 
+0

Va bene, vedo. Quindi, è possibile, quindi, definire le mie regole di coercizione di tipo? Ad esempio, se dovessi scrivere una classe Color, come potrei dire al compilatore che 'Color (0x443322)' è "un colore con 0x44 rosso, 0x33 verde e 0x22 blu"? –

+0

@David non è sicuro di come è impostata la tua classe di colore, ma di solito sono impostate come uint. Di solito qualcosa che si aspetta un colore si aspetta davvero un uint. il 0x di fronte significa che 0x443322 è un numero esadecimale, che si traduce in 4469438 uint. Quindi non dovresti aver bisogno di cambiarlo, ma se lo fai, penso che il modo migliore sarebbe quello di creare un metodo statico come Color.toColor (0x443322); –

Problemi correlati