La nouvelle méthode de programmation d'ActionScript 2 semble poser beaucoup de problèmes aux utilisateurs de la programmation évenementielle (dont je fais partie). En fait, mon problème essentiel avec l'AsBroadcaster existant porte sur deux points :
- On ne peut plus initialiser le prototype, mais uniquement l'instance (dans le constructeur)
- Si on veut une classe non-dynamique, il faut déclarer les fonctions addListener, removeListener et broadcastMessage.
Ma petite solution perso ne règle pas tous ces problèmes, dans le sens ou on ne peut pas faire de l'héritage dynamique, mais j'ai crée une classe nommée EventBroadcaster (je sais, le nom est pas top, mais j'ai pas osé LAlexBroadcaster, ca fait un peu mégalo ... :)).
class EventBroadcaster {
Elle peut être utilisée de deux manières :
var _listeners:Array;
// -- Constructeur
// Initialise le tableau '_listeners'
private function EventBroadcaster() {
this._listeners = new Array();
}
// Emet un évenement passé en paramètre
public function broadcastMessage (msg:String) {
// Parcoure le tableau '_listeners'
for (var i=0 ; i<this._listeners.length ; i++) {
// Si l'évenemet est présent dans un écouteur, on l'applique
// Avec les arguments passés aprés le nom de l'évenement
if (typeof this._listeners[i][msg] == "function") {
this._listeners[i][msg].apply(this._listeners[i],arguments.slice(1));
}
}
}
// Rajoute un écouteur a un objet
public function addListener(o:Object) {
// Supprime d'abord l'écouteur
this.removeListener(o);
// Ajoute l'objet en tant qu'écouteur
this._listeners.push(o);
}
// Supprime un écouteur
public function removeListener(o:Object) {
// Parcoure le tableau '_listeners'
// Si l'objet est trouvé, on le supprime et on arrete la boucle
for (var i=0 ; i<this._listeners.length ; i++) {
if (this._listeners[i] == o) {
this._listeners.splice(i,1);
break;
}
}
}
// Initialisation d'une instance de classe DYNAMIQUE
public static function initialize(o:Object) {
// On crée tout simplement le tableau '_listeners'
// et les méthodes pour broadcaster
o._listeners = new Array();
o.addListener = EventBroadcaster.prototype.addListener;
o.removeListener = EventBroadcaster.prototype.removeListener;
o.broadcastMessage = EventBroadcaster.prototype.broadcastMessage;
}
// Initialisation d'une classse DYNAMIQUE
// ou initialisation de la classe d'un instance DYNAMIQUE
// La classe doit être dinamique, tout simplement pour
// pouvoir faire appel a this.addListener ou this.broadcastMessage
public static function initializeClass(o:Object) {
var curParent:Object;
if (typeof o == "function") {
curParent = o.prototype;
} else {
curParent = o.__proto__;
}
do {
switch (curParent.__proto__) {
// La classe hérite deja de EventBroadcaster
case EventBroadcaster.prototype :
return;
// On est au niveau le plus bas de la chaine de protos
// On glisse le prototype dans la chaine
case Object.prototype :
curParent.__proto__ = EventBroadcaster.prototype;
return;
// Aucun des cas précédents, on remonte d'un cran dans
// la chaîne de prototypes
default :
curParent = curParent.__proto__;
}
} while (true);
}
}
- Par héritage
C'est de loin la méthode que je préfère, car elle ne nécessite pas une classe dynamique, ni une déclaration des méthodes de broadcast. Le seul inconvénient est que on n'a pas toujours le choix car l'héritage multiple n'existe pas en AS2. Mais on peut toujours faire hériter la classe mère de EventBroadcaster ...
class CustomClass extends EventBroadcaster {Et on l'utilise ainsi :
var _prop:Number = 10;
function CustomClass(prop:Number) {
this.addListener(this);
this._prop = prop;
}
function sendEvent() {
this.broadcastMessage("onEvent","Test d'évenement");
}
function onEvent(str) {
trace(str + " : " + this._prop);
}
}var myClass = new CustomClass(20);
myClass.sendEvent(); - Par l'utilisation de initialize ou initializeClass
- La méthode statique initialize fonctionne comme pour AsBroadcaster. Bien évidemment, il faut que la classe soit dynamique, pour pouvoir lui ajouter les fonction, et pouvoir appeler la méthode broadcastMessage dans les méthodes de la classe.
- La méthode initializeClass prend en paramètre soit une classe et fait hériter cette classe de EventBroadcaster, soit un objet et fait hériter la classe de cet objet de EventBroadcaster : c'est de l'héritage dynamique à l'aide de la chaine de prototypes.
dynamic class CustomClass {
var _prop:Number = 10;
function CustomClass(prop:Number) {
EventBroadcaster.initializeClass(this);
this._listeners = [];
this.addListener(this);
this._prop = prop;
}
function sendEvent() {
this.broadcastMessage("onEvent","Test d'évenement");
}
function onEvent(str) {
trace(str + " : " + this._prop);
}
}
Et l'utilisation est la même que celle donnée précédemment. L'avantage est que les méthodes addListener, removeListener et broadcastMessage ne se retrouvent pas dans chaque instance ...
Voila pour mon étude personnelle sur la question ! ![]()