Variables globales en AS3
Par Cédric Tabin le vendredi 14.03.2008, 22:26 - ActionScript - Lien permanent
En ActionScript 3, le mot-clé '_global' n'existe plus ! Et pour cause, avec la mise en place d'une philosophie complètement orientée objet et un langage beaucoup plus structuré, c'est à mon avis une bonne chose. Comment faire dès lors pour pouvoir accéder à certaines variables depuis n'importe où dans une animation ?
D'une manière générale, c'est très simple : il suffit de créer une classe avec des méthodes/propriétés statiques. Cela se résume en ceci dans un fichier Globals.as :
package { public class Globals { public static var language:String = "fr"; public static var currentVersion:String = "1.0a"; } }
Et dans l'animation :
trace(Globals.language); trace(Globals.currentVersion);
Toutefois, j'utilise très rarement ce procédé, tout simplement car cela regroupe toutes les variables dans une espèce de classe poubelle qui variera de projet en projet...
Je préfère utiliser la DocumentClass pour stocker les constantes relatives à mon application (si j'ai des variables, je les externalise dans un fichier texte), ce qui me donne ceci :
package { import flash.display.*; public class CurrentApplication extends MovieClip { public static const CURRENT_VERSION:String = "1.0a"; private static var __instance:CurrentApplication = null; public function CurrentApplication():void { __instance = this; } public static function getApplication():CurrentApplication { return __instance; } } }
Notez que souvent un projet doit gérer plusieurs langues. Il serait donc conceptuellement faux de placer une constante du type LANGUAGE à ce niveau là (une classe Language est bien plus indiquée) !
Encore une fois, chaque développeur/équipe à ses habitudes et je ne montre là que ma manière personelle de travailler. Et la vôtre ?
Commentaires
Pour ma part, j'ai aboli tout les singletons ou propriétés statiques dans le but de servir de stockage de données, je passe par des instances de managers ( languageManager, etc ) c'est beaucoup plus propre et ça me permet de faire evoluer l'application / code sans devoir refactoriser à un moment cette partie là si je veux pouvoir par exemple gerer plusieurs instance de version differentes de mon application ( cf ton exemple )
Salut NiKo,
Merci de ton retour !
Yep je suis d'accord avec toi J'ai aussi plusieurs managers, il y a généralement très peu de variables (ou plutôt de constantes) dans ma classe de Document, mais c'est toujours utile de pouvoir y accéder
Pour ce qui est d'avoir plusieurs instances de l'application, tu gères ça comment ? Je pense qu'il doit y avoir une erreur conceptuelle si tu en arrive à ce point...
@++
Yo
Pour moi une "application" n'est pas un Document ou un main Sprite, mais le model et l'ui qui vont avec, bref, un mvc.
Donc je peux tout à fait instancier plusieurs "application" dans un meme root Sprite, l'important à mes yeux, et de se donner le moins de limitation possible pour les futurs devellopements de l'application, donc non c'est pas une erreur conceptuel, au contraire.
A un moment, je peux avoir une demande pour permettre le lancement de plusieurs "application" au sein d'un meme swf avec passage de l'une à l'autre par x methodes.
Pour reparler de ton histoire d'acces global, pour moi l'acces global s'arrete à l'instance de l'application :
Ce que je fait c'est que je partage un eventdispatcher avec les managers de mon application, et par differents moyens j'ai un acces à cet eventDispatcher dans les plugins / ui qui m'interresse, ils peuvent donc lancer des demandes de type new AskEvent(AskEvent.type,this) et ils implementent une interface Asker qui a une methode answer (type:String,value:*) je peux donc leur repondre directement à partir des managers ou de tout autre classe qui ecoute cette demande là sur l'eventdispatcher partagé.
le singleton et les variables statiques sont de toutes manieres à utiliser vraiment avec parcimonie et à bon escient.
Enfin, chacun à sa vision des choses et c'est tant mieux, c'est comme ça que cela avance
slt,
ceci me parait plus logique:
package {
public class GlobalObjectManager extends Object {
private static const _GLOBAL:Object = new Object();
public function GlobalObjectManager() {
super();
Object.prototype.global = _GLOBAL;
}
}
}
// fla:
var gom:GlobalObjectManager = new GlobalObjectManager();
this.global.test = "test";
var mc:MovieClip = new MovieClip();
trace(mc.global.test);
>> NiKo, dans ce cas un Singleton est impératif
à noter q'un as3 tout est objet, donc l'accès à une variable globale ne poura de toute façon se faire que depuis un objet
++
Salut Pascal,
Oui effectivement, le souci c'est que tu refais un global ou tu peux à peu près mettre n'importe quoi L'idée est justement d'éviter cet objet 'poubelle' pour utiliser des constantes ^^ mais ta solution est tout à fait viable !
@++
... c ce que je pense, ce qui me fait dire que l'idée d'une variable _global n'a pas de sens en as3 ;
sauf à faire de l'import de classes à la volée sans les typer. cela permet des gains de poids assez conséquents. (c comme ça que j'avais conçu le SPAS 2).
mais avec ce procédé c'est la maintenance des projets qui en pâtit, en faisant les frais de l'abscence de typage (donc gros risques de bugs). bref à déconseiller !
++
Je suis le premier à clamer que le concept d'objet global est à bannir de toutes les bonnes architectures. Ceci dit, pour certains développeurs, je pense notamment aux designers flash ayant quelques notions de programmation, l'objet global est un outil efficace.
Voici l'implémentation que je conseil en général :
@@
package
{
import flash.utils.Dictionary;
public dynamic final class Register
{
private static var registers:Dictionary = new Dictionary();
public function Register(id:String = "")
{
if( Boolean(id) )
{
if(registers[id])
throw new ArgumentError(id + " is already declared as a register.");
else
registers[id] = this;
}
}
public static function getRegister(id:String):Register
{
if(!registers[id])
throw new ArgumentError(
id + " is not declared as a register. " +
"Use declareRegister(id) prior to retrieve " +
"it with getRegister(id).");
return registers[id];
}
public static function declareRegister(id:String):Boolean
{
var exist:Boolean = false;
if(!registers[id])
registers[id] = new Register();
else
exist = true;
return exist;
}
public static function removeRegister(id:String):Boolean
{
var wasRemoved:Boolean = true;
if(registers[id])
registers[id] = null;
else
wasRemoved = false;
return wasRemoved;
}
public static function hasRegister(id:String):Boolean
{
return registers[id] != null;
}
}
}
@@
@@
package
{
public function get register():Register
{
var id:String = 'global';
if(!Register.hasRegister(id))
Register.declareRegister(id);
return Register.getRegister(id);
}
}
@@
Restons objet