2009-06-15 12 views
18

Por lo que entiendo de ActionScript, hay dos tipos de moldes:ActionScript: ¿Hay alguna vez una buena razón para usar 'como' casting?

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

También, y por favor, corríjanme si me equivoco aquí, as de fundición o bien devolver una instancia de la clase o null, mientras El casting de "nombre de clase" devolverá una instancia de la clase o generará una excepción si el reparto es imposible; además de esto, son idénticos.

Teniendo en cuenta esto, as fundición parece ser una violación masiva del principio fail-fast-fail-early ... Y estoy teniendo problemas para imaginar una situación en la que sería preferible usar un molde as en lugar que un molde de nombre de clase (con, posiblemente, un instanceof arrojado allí).

Entonces, mi pregunta es: ¿bajo qué circunstancias sería preferible usar as de fundición?

+0

nota de que el enlace en tiempo, en general, que a menudo es útil, está en conflicto directo con su interpretación de fffe. – dkretz

+0

Es cierto, también es inevitable en ActionScript, ya que no existe la noción de "genéricos", por lo que las cosas que obtienes de los contenedores estarán sin tipo. –

+0

(por lo que es preferible fallar en 'var foo: Foo = Foo (myArray [i])' en lugar de obtener un nulo y tratar con un NPX en otro lugar) –

Respuesta

12

Debe usar as para emitir en dos escenarios: fundición a Date, y fundición a Array.

Para las fechas, una llamada a Date(xxx) se comporta igual que la nueva Date().toString().

Para las matrices, una llamada a Array(xxx) creará un Array con un elemento: xxx.

El método de fundición Class() ha demostrado ser más rápido que as de fundición, por lo que puede ser preferible as cuando los asuntos de eficiencia (y cuando no está trabajando con las fechas y matrices).

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

Utilice 'como' con arreglos.

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

Producirá una matriz de longitud uno con la matriz original en el primer elemento. Si usa 'como' de la siguiente manera, obtiene el resultado de exptected.

var goodArray:Array; 
goodArray = obj as Array; 

Generalmente, 'como' es preferible 'Clase()' en ActionScript como se comporta más como fundición en otros idiomas.

+1

Cuando dice "otros idiomas", ¿en qué piensa? ? Sé con certeza que Java lanzará una excepción si intenta realizar un lanzamiento incorrecto ... –

+0

Java convertirá una lista correctamente si lo hace List list = (List ) obj; Sin excepción, no hay problema. Usted hace Array (obj) en AS, problema. – stevedbrown

26

Hay un par de puntos en esta discusión digno de mención.

Hay una gran diferencia en la forma en que los dos trabajan, Class() intentará convertir el objeto a la clase especificada, pero si no lo hace (a veces, depende del tipo de datos) arrojará un error de tiempo de ejecución. Por otro lado, usar object como Class preformará una verificación de tipo primero, y si el objeto especificado no se puede convertir a la clase indicada, se devolverá un valor nulo.

Esta es una diferencia muy importante, y es una herramienta útil en el desarrollo. Nos permite hacer lo siguiente:

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

if(o) 
{ 
    //do stuff 
} 

Creo que la utilidad de eso es bastante obvia.

"as" también es más consistente con el resto del lenguaje (es decir: "myObject es MyClass").

El método MiClase() tiene beneficios adicionales cuando se trabaja con tipos simples de datos (int, número, los uint, String) Algunos ejemplos de esto son:

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 

Este es un tema bueno e importante, como una regla general uso "como" cuando trabajo con Objetos y Cast() cuando uso tipos de datos más simples, pero así es como me gusta estructurar mi código.

+0

'as' puede ser más consistente con el idioma, pero ¿no es aún más peligroso? Gracias por la respuesta, sin embargo, las complejidades de int/string/number casting son buenas de conocer. –

+0

¿Qué sientes es más peligroso al respecto? Lo peligroso no es manejar todas las situaciones de manera adecuada, sino que se trata de un problema de desarrollador no de idioma. De hecho, creo que es más seguro (comprobación de tipos) e increíblemente útil, y puede dar como resultado un código más limpio. var o: Clase = a [i] como clase || Nueva clase(); // ideal para este tipo de cosas –

+0

Para aclarar por qué creo que es más seguro: te permite intentar un tipo de elenco sin romper cosas si falla. –

0

Lo uso cuando tengo un ArrayCollection de objetos y necesito enumerarlos a través de ellos, o usar una función de selector.

p. Ej.

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

+0

¿Pero por qué usas 'as' sobre' var abc: MyType = MyType (mycollection.getItemAt (i)) '? Usar 'as' introduce la posibilidad de una falla sutil si' mycollection' contiene algo que no es 'MyType' (vea la regla de fail-fast) –

+0

Lo uso porque para mí MyType (...) es mentalmente un cast y "como MyType" es mentalmente un alias, y no estoy lanzándolo, sino más bien afirmando que eso es lo que hace que el compilador sea feliz (incluso si pudieran ser los mismos en este caso). Pero estoy en el extremo de la curva en forma de campana, así que probablemente sea más que nada un reflejo de cómo pienso en el código, prefiero que sea claro y simple que se abroche en todas las esquinas. Me alegra que dejaran javascript suficientemente bien solo en lugar de hacer actionscript de él. También utilizo bastante el constructo "if (! Object) {}" mencionado en otra respuesta. – dkretz

5

En realidad, hacen cosas diferentes ... cuando dices

myvar as ClassName 

Usted está realmente sólo dejar que el compilador sabe que este objeto es o bien un nombre de clase o una subclase de NombredeClase

cuando dice:

ClassName(myvar) 

Realmente intenta convertirlo a ese tipo de objeto.

así que si su objeto es una o un descenso de la clase y no es necesario para convertirlo usaría como

ejemplos:

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

Bien, ya veo. Entonces, ¿es posible definir mis propias reglas de coerción de tipo? Por ejemplo, si tuviera que escribir una clase de Color, ¿cómo podría decirle al compilador que 'Color (0x443322)' es "un color con 0x44 rojo, 0x33 verde y 0x22 azul"? –

+0

@David no está seguro de cómo está configurada su clase de color, pero generalmente se configuran como uint. Por lo general, algo que está esperando un color realmente espera una uint. el 0x al frente significa que 0x443322 es un número hexadecimal, lo que se traduce en 4469438 uint. Por lo tanto, no debería necesitar cambiarlo, pero si lo hace, creo que la mejor manera sería crear un método estático como Color.toColor (0x443322); –

Cuestiones relacionadas