Cómo comunicar clases en AS3
4 seguidores
¡Buenas!
Por fin estoy empezando con as3, y después de haberme montado más o menos todo estoy en un callejón sin salida.
Tengo una clase general, dónde instancio demás clases y con funciones generales. El tema es que tengo una clase menu, y otra clase contenido, ambas las llamo desde la clase principal.
El menu tiene distintos botones, y me gustaría que al clicar cada uno de los botones dentro de la clase menu, tuvieran un efecto en la clase contenedor. Para eso supongo que tengo que pasar por la clase principal, y la verdad es que no sé cómo enlazarlo.
Alguna ayuda o idea de cómo enfocarlo me vendría genial. Gracias de antemano.
Usuario desconocido
Desde mi punto de vista hay dos metáforas. Global o modular, implementando Modelo, Vista, Controlador.
Modelo
En el modelo se conservan todos los objetos, variables y estados de la aplicación, de modo que te baste conocer el modelo para comprender el total de la aplicación.
Vistas
Las vistas son componentes "tontos" y parametreables, que pueden representar partes del modelo.
Controlador
La lógica y comunicación de tu aplicación (lo que tu llamas director u orquestador).
Comunicación centralizada o modular
Aquí la metáfora a aplicar es la de condominio horizontal (cada casa con su agua, luz, clima, etc) o la de condominio vertical (un gran contenedor de agua, un gran switch de luz y un clima centralizado)
Si escoges el modular, cada componente poseerá un pedazo del modelo y de la lógica de la aplicación, y deberá de comunicarse con el resto de los componentes.
Si escoges global, entonces cada componente deberá reportarse con un evento, tipo de evento y parámetros de evento con la clase "EventManager" general, y esta tomara las decisiones pertinentes. Incluso cuando inicies la aplicación, el controlador de tu aplicación, será quien asigne los eventos a los componentes.
custo
¡elSuricatoRojo muchísimas gracias!
Lo has explicado al dedillo, ya he conseguido hacerlo tal y como tú dices, llamando a un método público de la clase general, y desde la general lanzando los eventos que cada una de las clases va escuchando.
He creado una clase dispatcher singleton, y cada una de las clases tienen la instancia de dispatcher con lo que escuchan los eventos lanzados por la general.
Lo único que me queda por hacer es pasar parámetros dentro de los eventos, es posible? Estoy buscando cómo hacerlo pero no encuentro nada que sea sencillo y entendible.
EDITO: He encontrado cómo pasar parámetros al evento. Tengo dos opciones:
1. Creando una nueva clase Evento subclasse de Event y que permita parámetros.
2. A la clase dispatcher que he creado le añado la propiedad number, y mediante dispacther.number le asigno la id del botón clicado, rescatándo después dentro de cada clase con e.target.number.
¿Cúal sería la mejor opción?
Gracias de nuevo
elSuricatoRojo
Custo insisto que es muy recomendable utilizar eventos en la comunicación entre clases, no siempre por supuesto, pero deberias intentar avanzar por ese camino.
La idea de los eventos es muy sencilla. Existe una entidad que tiene 1) la capacidad de registrar oyentes a determinados eventos y 2) tiene la cacidad de emitir esos eventos.
La gracia de todo esto es que la entidad "emisora" no tiene que saber a priori cuantos oyentes va a tener. La entidad emisor tan solo emite eventos ante determinados sucesos y se despreocupa de quien los oye.
Empápate de la clase EventDispacher de AS3 (de ella y de las que heredan de ella que son un huevo.. lo cual es otra pista de lo importante que es). Haz algún tutorial sencillo donde se utilicen los eventos y almacena ese conocimiento. Un día le perderás el miedo a utilizarlo en un proyecto real y apartir de de ahí, creo, programará siempre con ellos.
Tampoco deseches la comunicación basada en métodos públicos. Es otra herramienta mas y en ocasiones es tan buena opción como los eventos.
Te pongo un ejemplo de como utilizo yo los eventos y las llamadas a metodos públicos:
1) Tengo una entidad que actua como lógica principal, document class, o como quieras llamarla, pero que basicamente actua como director de orquesta a nivel general de la aplicación. Tiene la capacidad de registrar oyentes y emitir eventos.
2) Tengo, digamos un menu con "n" opciones. De tal forma que cuando se pincha en una opción esta se queda seleccionada.
3) Tengo un fondo de color de tal forma que según la opción seleccionada el fondo muestra un color u otro.
4) Tengo una zona de contenidos de tal forma que en base a la opción seleccionada carga un swf de contenidos u otro.
5) Hago oyentes a "menu", "fondo" y "contenidos" de la lógica principal, del evento "onOpcionSeleccionada" (AS2) o el evento que crees al efecto en AS3.
6) En el menu, al pinchar en una opción esta no se queda seleccionada directamente. En cambio le comunica esa selección a la lógica principal accediendo a un método publico: logica.seleccionarOpcion(opcionId).
7) La logica principal emite el evento "onOpcionSeleccionada" (AS2) o el evento creado al efecto en AS3, pasando como parámetro la opciónId recibida como seleccionada.
8 ) Las 3 entidades "menu", "fondo" y "contenidos" reciben el evento y actuan en consecuencia... el fondo cambia el color al asociado a la opcionId pasada en el evento, los contenidos cargar el swf asociado a la opcionId pasada en el evento, y el menu selecciona el botón asociado a la opcionId.
9) Al principio puede parecer raro que el botón del menú no se autoseleccione al pinchar sobre el, pero es mejor, IMHO, que lo haga en base al evento recibido de la logica principal..por que? porque esto te va permitir seleccionar opciones sin utilizar el menu (consiguiendo que éste se actualice a la nueva opcion seleccionada), tan solo llamando a logica.seleccionarOpcion(opcionId). Si haces un segundo menú, tan solo tienes que registrarlo como oyente de logica y a correr.. es un poco plug&play.
10) En resumen, el seleccionar una opción se hace llamando a un método público de la lógica principal. Las consecuencias de esa selección se propagan mediante eventos.
11) Lo unico que queda es tener una referencia de la lógica principal. Ésta puede ser un singelton y obtener la referencia mediante su acceso estático, por ejemplo: logica = LogicaPrincipal.getInstance(), o accediendo de forma absoluta (_level0.logica en AS2 o stage en AS3), o pasandola como parámentro en las constructoras, etc
no me enrollo mas y duro con EventDispatcher :-)
custo
Gracias ozke y suricato por vuestras respuestas. ;)
Aunque entiendo el método que propone suricato no sé cómo llevarlo a cabo. De momento lo he realizado como me ha comentado ozke y funciona perfectamente, pero claro, no sé si el tema de hacer muchos métodos públicos e irlos llamando es poco óptimo... ya que ya que empiezo me gustaría hacerlo sobre una buena base...
Gracias!
ozke
suricato tiene razon... usar eventos y listeners es una de las formas. Lo cierto es que depende de que quieras hacer. De si es un template comunicandose con otro template generico... en cuyo caso te recomendaria herencia... de si es una clase que haga de interface de la aplicacion... el fin el tema es complejo.
Si estas empezando, y para hacer las cosas faciles usa esto...
Imagino que tienes tu document class... y en ella tienes algo asi como
menu = new Menu();
contenido = new Contenido();
pues haz esto...
menu = new Menu(this);
contenido = new Contenido(this);
ahora... desde cualquier clase podras guardar una referencia a la doc class
function constructorEjemplo(_doc_class:*){
doc_class=_doc_class;
}
y listo!
desde el menu al contenido...
doc_class.contenido.loquesea();
hay mucha gente que a esto (o algo parecido) le llama topClass.
Si lo "googleas" encontraras mucha cosa :)
elSuricatoRojo
Por lo general la mejor forma de comunicar clases es mediante eventos. Lo otra opción es llamando a métodos públicos. En tu caso yo haría 2 "comunicaciones"...
1) Que el menu comunique a la clase pricipal que opción se ha escojido. En este caso puedes hacer oyente la clase principal del menú pero tambien puedes habilitar un método publico en la clase principal. Normalmente el acceso a la clase principal suele ser facil e incluso puede ser un singelton lo cual lo hace mas fácil todavía por lo que el método público puede ser una opción.
2) La clase principal emite un evento comunicando a quien esté suscrito como oyente a ese evento que se ha escojido una opción. Aquí si que es fundamental que la comunicación sea por eventos ya que si hoy es solo la parte del contenido que reacciona a una hipotética selección de una opción en el menú, mañana pueden ser 2, 3 o mas. Ir uno por uno llamando a clases públicas sería un error grave. Emitir un evento sin saber quien lo escuchará es, IMHO, el camino correcto y hará tu aplicación mucho mas escalable.