Consejo rápido: Cómo depurar un error AS3 #1120
() translation by (you can also view the original English article)
Un error de ActionScript muy común es el error 1120, el error de "propiedad indefinida". De hecho, este puede ser el error en tiempo de compilación más común. Su causa es muy simple, pero hay varias formas de inducirla. Haremos un recorrido rápido por algunos de los escenarios en los que encontrarás este error y cómo solucionarlos.
La explicación
Primero, tengamos una idea general de lo que está sucediendo con este error. Esta será nuestra discusión teórica; llegaremos a ejemplos más prácticos en el resto del consejo.
Encuentras que este error ocurre cuando haces referencia a una variable (o propiedad) en una línea de código, pero esa variable no existe. Si estás acostumbrado a escribir ActionScript en el panel Script y no en clases, no te dejes intimidar por el término "propiedad". No entraré en una discusión extensa sobre por qué tenemos estos dos términos, pero basta con decir que, dada la forma en que ActionScript compila el código desde el panel Script, una variable es en realidad una propiedad.
Si el compilador de ActionScript no puede encontrar la propiedad que has especificado, la marca con el error de compilador 1120. Verás algo como esto:
1 |
1120: Access of undefined property foo. |
Donde "foo
" es el nombre de tu propiedad ofensiva.
Resolver esto suele ser tan fácil como conseguir el nombre correcto. Vamos a ver.
Ejemplo 1: Declaración sin variable
Toma este código, por ejemplo (si lo deseas, puedes abrir el proyecto de ejemplo "missing" (es decir, el proyecto llamado "missing" en la descarga de código fuente) o crear este proyecto por tu cuenta: simplemente crea un nuevo archivo Flash y una clase "Document" para él, y coloca este código en la clase de "Document"):
1 |
package { |
2 |
import flash.display.*; |
3 |
public class Missing extends Sprite { |
4 |
|
5 |
public function Missing() { |
6 |
|
7 |
foo = "Moo."; |
8 |
|
9 |
}
|
10 |
}
|
11 |
}
|
Compila este FLA y obtendrás el error 1120: Access of undefined property foo.
, dirigido a la línea 7.
Una vez más, la causa probablemente sea muy clara; nunca has declarado la propiedad foo
y, por lo tanto, usarla en la línea 7 como si ya existiera causa problemas. La solución es simplemente declarar la variable. Técnicamente, esto puede existir en cualquier lugar del ámbito apropiado. Cada una de las siguientes son soluciones aceptables:
Decláralo como parámetro del método:
1 |
public function Missing(foo:String) { |
2 |
|
3 |
foo = "Moo."; |
4 |
|
5 |
}
|
Decláralo como una variable local dentro del método:
1 |
public function Missing() { |
2 |
var foo:String; |
3 |
foo = "Moo."; |
4 |
|
5 |
}
|
Decláralo como una propiedad de instancia en la clase:
1 |
package { |
2 |
import flash.display.*; |
3 |
public class Missing extends Sprite { |
4 |
|
5 |
private var foo:String; |
6 |
|
7 |
public function Missing() { |
8 |
|
9 |
foo = "Moo."; |
10 |
|
11 |
}
|
12 |
}
|
13 |
}
|
La solución depende de lo que sea apropiado para lo que intentes hacer. No es común declarar un parámetro de método y luego simplemente establecerlo en el contenido del método, aunque hay casos en los que deseas afectar los valores del parámetro.
Lo que puedes resultar interesante es la forma en que Flash buscará una variable del nombre. Primero, busca una variable local con el nombre foo
. Si uno no fue declarado, entonces mira los parámetros para ese nombre. Si no puede encontrar uno allí, busca una propiedad de instancia con el mismo nombre. Si no se encuentra ninguno de estos, verás el error 1120.
Ejemplo 2: Un error tipográfico
Nuestro siguiente ejemplo será bastante similar. De nuevo, simplemente puedes abrir el proyecto "typo" desde la descarga; o crea un FLA simple con la clase "Document" y pega/escribe el siguiente código en la clase; o simplemente sigue leyendo.
1 |
package { |
2 |
import flash.display.*; |
3 |
public class Typo extends Sprite { |
4 |
|
5 |
var foo:String; |
6 |
|
7 |
public function Typo() { |
8 |
|
9 |
boo = "Moo."; |
10 |
|
11 |
}
|
12 |
}
|
13 |
}
|
No pasa mucho aquí. La idea es declarar una propiedad llamada foo
, y luego en el constructor establecerla en el valor "Moo
". La esencia de esto está en las líneas 5 y 9, resaltadas arriba. El resto es solo texto repetitivo de la clase "Document".
Una vez más, el error probablemente sea dolorosamente obvio. Y, por supuesto, lo es, cuando solo hay dos líneas de código de las que preocuparte. Claramente tenemos un error tipográfico; queríamos escribir:
1 |
foo = "Moo."; |
Y si corriges el error tipográfico, podrás compilar el FLA sin el error 1120.
Si bien este es obvio, quiero hacer dos notas. La primera es que los errores tipográficos como este son en realidad algo comunes y más difíciles de deducir cuando tienes miles de líneas de código en tu proyecto. Un buen IDE o editor de texto puede ayudarte al proporcionar autocompletado u otros tipos de verificación de errores, pero como ActionScript a prueba de fallas también te ayudará produciendo el Error 1120.
La segunda nota es que el error que ActionScript realmente informa es que estás intentando hacer referencia a una propiedad llamada "boo
", pero no encuentra ninguna. En este ejemplo, hemos producido el error al introducir un error tipográfico en nuestro código. Pero ActionScript no sabe que realmente quisiste decir "foo
"; asume que cuando escribes "boo = "Moo.";
" quisiste decir boo
, y te advierte cuando no puede encontrar una propiedad con ese nombre.
Esta es una distinción bastante sutil, pero es útil tener en cuenta la verdadera causa del error.
Ejemplo 3: Declaración de instancias de etapa
Nuestro ejemplo final involucra el IDE de Flash en particular, y puede ignorarse con seguridad si no estás usando Flash CS3/4/5, y en su lugar usa Flash Builder con Flex Framework. La configuración del error tomará unos sencillos pasos.
Puedes encontrar el proyecto problemático en la carpeta stage-instance de descarga. O puedes volver a crearlo siguiendo estos pasos:
- Comienza con un nuevo archivo Flash y la clase "Document" asociada.
- En el archivo Flash, dibuja una forma de algún tipo y conviértela en un símbolo.
- Selecciona la instancia del símbolo en el escenario y abre el panel "Propiedades", y asigna un nombre a la instancia
instance_mc
. - Aún en Flash, elige Archivo > Configuración de publicación y luego selecciona la pestaña Flash.
- Haz clic en el botón Configuración... junto al menú emergente "Script:".
- Donde dice Escena: Declarar automáticamente instancias de etapa, asegúrate de que la casilla de verificación no esté seleccionada.
-
Agrega el siguiente código a la clase "Document":
1
package {
2
import flash.display.*;
3
public class StageInstance extends Sprite {
4
public function StageInstance() {
5
instance_mc.rotation = 45;
6
}
7
}
8
}
En este punto, continúa y ejecuta la película. Una vez más obtendrás el error 1120.
Como puedes suponer, desactivar "Declarar instancias de etapa automáticamente" tuvo mucho que ver con la generación del error. Es una opción que está activada de forma predeterminada, por lo que probablemente tengas una razón para estar pendiente y ser consciente de desactivarla.
Lo que hace es bastante autoexplicativo, pero agregaré mis dos centavos. Cuando tienes una clase "Document" (o una clase personalizada vinculada a un símbolo en la biblioteca), esa clase extiende de Sprite
o MovieClip
. Las reglas típicas para crear variables y propiedades se aplican como cualquier otra clase, pero debido a que tienes una interfaz visual para este objeto, el IDE de Flash, es posible que estés agregando propiedades implícitamente dibujando más símbolos en el escenario y dándoles nombres de instancia.
Si "Declarar instancias de etapa automáticamente" está activado, Flash pasará por los objetos agregados a la etapa a través del IDE e insertará declaraciones de propiedad en las clases apropiadas para cada instancia de símbolo con un nombre.
Si está apagado, Flash no hará nada con las instancias en el escenario.
Para evitar el error, simplemente puedes volver a activar esta opción. Alternativamente, puedes declarar manualmente las instancias de etapa. Si hicimos que nuestra clase "Document" se viera así:
1 |
package { |
2 |
import flash.display.*; |
3 |
public class StageInstance extends Sprite { |
4 |
|
5 |
public var instance_mc:MovieClip; |
6 |
|
7 |
public function StageInstance() { |
8 |
instance_mc.rotation = 45; |
9 |
}
|
10 |
}
|
11 |
}
|
Esto también evitaría el error, porque la propiedad todavía está declarada; simplemente no ha sido declarado automáticamente por Flash Professional.
Ten en cuenta que si el modificador de acceso no es público
, obtendrás un error de tiempo de ejecución. No voy a entrar en detalles sobre este error; eso será para otro consejo rápido.
Ahora, ¿por qué querrías desactivar esa opción en primer lugar? Creo que todas las razones tienen que ver con ir más allá de Flash como herramienta de desarrollo. Si usas Flash Builder para programar, o ASDoc, o integras contenido Flash dentro de un proyecto Flex, es posible que aprecies las ramificaciones de desactivar la opción. Si lo apagas, te verás obligado a declarar las propiedades manualmente. Lo contrario también es cierto: si lo enciendes, te ves obligado a no declarar manualmente esas propiedades.
Por lo tanto, si ejecutas tus archivos de clase a través de ASDoc, lo más probable es que encuentres una referencia a una instancia de etapa, pero no a su declaración, y recibirás el error 1120. Activar la opción es conveniente, pero desactivarla te obliga escribir código más "puro" que sea más portátil y autónomo.
Declaro terminado este consejo rápido
Como muchos errores, el error 1120 es simple en el fondo y fácil de corregir una vez que sepas qué buscar. Gracias por leer, y espero que estés atento para más consejos rápidos de depuración.