Simuler une énumération et/ou des contantes
Par -Alexandre LEGOUT aka LAlex- le 22 décembre 2005, 14:12 - AS2 - Lien permanent
Il peut être trés pratique, voire parfois indispensable pour obtenir un code "clean", de ne pouvoir passer une valeur à une méthode, qui doit obligatoirement être une des valeurs "possibles"... C'est ce que l'on appelle des énumérations. Java gère cela nativement grâce à la classe Enum.
De même, avoir la possibilité de créer des constantes est également bien utile. Dans la pratique, il s'agit en fait de créer une propriété statique en lecture seule. Le moyen le plus sûr de faire cela serait de créer une variable statique privée, et un getter statique public.
Voici ce que cela pourrait donner dans le cadre d'une classe d'encryptage:
class Crypter {
Bien que tout cela soit quand-même assez clean, cette implémentation pose quelques problèmes:
// Private static members
private static var _NONE:String = "none";
private static var _MD5:String = "md5";
private static var _SHA1:String = "sha1";
// Public constants
public static function get NONE():String {
return _NONE;
}
public static function get MD5():String {
return _MD5;
}
public static function get SHA1():String {
return _SHA1;
}
private var _cryptMode:String;
function Crypter(mode:String) {
_cryptMode = mode;
}
function encrypt(s:String):String {
// Case use private vars, to avoid decreasing
// performances by using a getter
switch(_cryptMode) {
case _NONE:
return s;
case _MD5:
var md5crypted:String = "";
// Perform MD5 cryptage
return md5crypted;
case _SHA1:
var sha1crypted:String = "";
// Perform SHA1 cryptage
return sha1crypted;
}
}
}
// Usage
var myCrypter:Crypter = new Crypter(Crypter.MD5);
trace(myCrypter.encrypt("String to be encrypted"));
- Tout accés aux constantes (de l'exterieur) fait appel à un getter, et donc les performances peuvent s'en ressentir, selon la fréquence de ces accés
- Il est possible de passer au constructeur une chaine de caractères qui ne fasse pas partie des valeurs attendues en entrée... Cela peut se résoudre avec un default: dans le case, mais ce n'est pas vraiment une solution satisfaisante...
// Enum
class CryptMode
extends String {
public static var NONE:CryptMode = new CryptMode("none");
public static var MD5:CryptMode = new CryptMode("md5");
public static var SHA1:CryptMode = new CryptMode("sha1");
private function CryptMode(content:String) {
super(content);
}
}
class Crypter {
private var _cryptMode:CryptMode;
function Crypter(mode:CryptMode) {
_cryptMode = mode;
}
function encrypt(s:String):String {
// Case use private vars, to avoid decreasing
// performances by using a getter
switch(_cryptMode) {
case CryptMode.NONE:
return s;
case CryptMode.MD5:
var md5crypted:String = "";
// Perform MD5
return md5crypted;
case CryptMode.SHA1:
var sha1crypted:String = "";
// Perform SHA1
return sha1crypted;
}
}
}
// Usage
var myCrypter:Crypter = new Crypter(CryptMode.MD5);
trace(myCrypter.encrypt("String to be encrypted"));
Cette méthode à tous les avantages:- Impossible de rajouter des constantes non-prévues au runtime, du fait du constructeur privé.
- Toujours grâce au constructeur privé, impossible de modifier la valeur d'une constante, bien qu'il s'agisse d'une propriété publique.
- Impossible de passer une valeur non prévue à une méthode, si l'argument est typé avec l'énumération.
- Une compatibilité avec les types de bases. Bien que l'exemple se base sur un héritage de String, il est bien sûr possible de l'utiliser sur n'importe quel type "de base" (Number par exemple) comme sur des types plus complexes. Le '==' continue de fonctionner par exemple :
trace(CryptMode.MD5 == "md5"); // true
- Petit bémol, le switch...case semble utiliser une comparaison stricte (===), donc ne pas oublier de faire un toString() ou valueOf() dans ce cas...

- Remplace presque parfaitement le fait de ne pas pouvoir créer de constantes dans les interfaces, offrant ainsi la possibilité de disposer d'une série de valeurs dans la création d'une API "pure" (sans aucune implémentation).
Bref, je suis assez content d'avoir trouvé ce moyen de rendre mes codes un peu plus clean. J'utilise dorénavant énormément cette astuce, notamment concernant la diffusion d'évenements, en créant une classe collection contenant les évenements diffusables par une classe définie, puis en utilisant le typage dans la signature de mes addEventListener (en parlant de ça, bientôt un tool de diffusion d'évenements maison).
Wala, wala! ^^
Commentaires
C'est marrant car moi aussi j'utilise cette méthode .. surtout qu'avec les constantes en AS3 on prend vite gout à l'utilisation d'une classe spécifique pour les Constantes par exemple au niveau des EventType.
Donc la méthode de Francis est la plus stable.
.. enfin c'est la vie hein 
Parfois aussi j'utilise une classe Constant qui peut servir à rendre complètement inaccessible certaines propriétés.. seul petit problème c'est que j'utilise cette classe en interne dans une classe AS2... en passant par un constructeur static de classe et qui doit normalement initialiser via un tableau toutes mes propriétés statiques qui doivent devenir une constante... mais malheureusement cela ne fonctionne pas à tous les coups
/* ------- ConstantAUTHOR
Name : Constant
Package : vegas.util
Version : 1.0.0.0
Date : 2005-10-18
Author : ekameleon
URL : <a href="http://www.ekameleon.net" rel="nofollow">http://www.ekameleon.net</a>
Mail : <a href="mailto:contact@ekameleon.net" rel="nofollow">contact@ekameleon.net</a>
CONSTRUCTOR
var c:Constant = new Constant(o:Object, prop:String) ;
METHODS
- toString()
STATIC METHODS
- setConstants(o:Object, props:Array):Void
---------- */
import vegas.util.ToString ;
class vegas.util.Constant implements ToString {
// ----o Author Properties
public static var className:String = "Constant" ;
public static var classPackage:String = "vegas.util" ;
public static var version:String = "1.0.0.0";
public static var author:String = "ekameleon";
public static var link:String = "<a href="http://www.ekameleon.net" rel="nofollow">http://www.ekameleon.net</a>" ;
// ----o Construtor
public function Constant(o, prop:String) {
_global.ASSetPropFlags(o, [prop], 7, 1) ;
}
// ----o Static Methods
static public function setConstants(o, props:Array):Void {
var len:Number = props.length ;
while(--len > -1) {
var c:Constant = new Constant(o, props[len]) ;
}
}
// ----o Public Methods
public function toString():String {
return "[Constant]" ;
}
}
Je suis en train de faire un refactoring complet sur mon framework à ce niveau là... dommage que macromedia n'est pas pri le temps de mettre le mot clé const directement dans flash 8
EKA+
tu peux modifier la constante avec
CryptMode["MD5"] = "truc";ou avec un castCryptMode.MD5 = CryptMode("bidule"); // nullmais de toute facon, peu importe la valeur puisqu'on teste toujours avec la la variable statique c'est vrai que ca pourrait gênant avec un test commeCryptMode.MD5 == "md5"pourquoi le default n'est pas satisfaisant ? on peut aussi ne rien passer en paramêtre et dans ce cas, la méthode encrypt n'a aucun retour
l'avantage, comme sur pixlib, c'est pour le typage
Oui c'est clair neo-lao .. c'est pas suffisant pour la notion de constante...
Disons que c'est lourd en fait de faire une vraie Constant ... j'ai un peu corrigé ma classe Constant au dessus au passage :
/* ------- ConstantUtilisation dans une classe StageAlign . (polymorphe avec la classe AS3 du même nom)AUTHOR
Name : Constant
Package : vegas.util
Version : 1.0.0.0
Date : 2005-10-18
Author : ekameleon
URL : <a href="http://www.ekameleon.net" rel="nofollow">http://www.ekameleon.net</a>
Mail : <a href="mailto:contact@ekameleon.net" rel="nofollow">contact@ekameleon.net</a>
CONSTRUCTOR
new Constant(o:Object, prop:String) ;
METHOD SUMMARY
- static setConstants(o:Object, props:Array):Boolean
- toString()
IMPLEMENTS
ToString
---------- */
import vegas.util.ToString ;
class vegas.util.Constant implements ToString {
// ----o Author Properties
public static var className:String = "Constant" ;
public static var classPackage:String = "vegas.util" ;
public static var version:String = "1.0.0.0";
public static var author:String = "ekameleon";
public static var link:String = "<a href="http://www.ekameleon.net" rel="nofollow">http://www.ekameleon.net</a>" ;
// ----o Construtor
public function Constant(o, prop:String) {
_global.ASSetPropFlags(o, [prop], 7, 1) ;
}
// ----o Static Methods
static public function setConstants(o, props:Array):Boolean {
if (o && props.length > 0) {
_global.ASSetPropFlags(o, props, 7, 1) ;
return true ;
} else {
return false ;
}
}
// ----o Public Methods
public function toString():String {
return "[Constant]" ;
}
}
/* -------- StageAlignAUTHOR
Name : StageAlign
Package : vegas.display
Version : 1.0.0.0
Date : 2005-11-18
Author : ekameleon
URL : <a href="http://www.ekameleon.net" rel="nofollow">http://www.ekameleon.net</a>
Mail : <a href="mailto:contact@ekameleon.net" rel="nofollow">contact@ekameleon.net</a>
CONSTRUCTOR
new StageAlign(align:String) ;
CONSTANT SUMMARY
BOTTOM:StageAlign
Specifies that the Stage is aligned at the bottom.
BOTTOM_LEFT:StageAlign
Specifies that the Stage is aligned in the bottom-left corner.
BOTTOM_RIGHT:StageAlign
Specifies that the Stage is aligned in the bottom-right corner.
LEFT:StageAlign
Specifies that the Stage is aligned on the left.
RIGHT:StageAlign
Specifies that the Stage is aligned to the right.
TOP:StageAlign
Specifies that the Stage is aligned at the top.
TOP_LEFT:StageAlign
Specifies that the Stage is aligned in the top-left corner.
TOP_RIGHT:StageAlign
Specifies that the Stage is aligned in the top-right corner.
METHOD SUMMARY
- static getAlign(align:String, default_align:StageAlign):String
------------*/
import vegas.util.Constant ;
class vegas.display.StageAlign extends String {
// ----o Author Properties
public static var className:String = "StageAlign" ;
public static var classPackage:String = "vegas.display";
public static var version:String = "1.0.0.0";
public static var author:String = "ekameleon";
public static var link:String = "<a href="http://www.ekameleon.net" rel="nofollow">http://www.ekameleon.net</a>" ;
// ----o Constructor
public function StageAlign(align:String) {
super(align) ;
}
// ----o Public Properties
static public var BOTTOM:StageAlign = new StageAlign("B") ;
static public var BOTTOM_LEFT:StageAlign = new StageAlign("BL") ;
static public var BOTTOM_RIGHT:StageAlign = new StageAlign("BR") ;
static public var CENTER:StageAlign = new StageAlign("") ;
static public var LEFT:StageAlign = new StageAlign("L") ;
static public var RIGHT:StageAlign = new StageAlign("R") ;
static public var TOP:StageAlign = new StageAlign("T") ;
static public var TOP_LEFT:StageAlign = new StageAlign("TL") ;
static public var TOP_RIGHT:StageAlign = new StageAlign("TR") ;
// ----o Public Methods
static public function getAlign(align:String, default_align:String):StageAlign {
var aligns:Object = {
B : BOTTOM , BL : BOTTOM_LEFT , BR : BOTTOM_RIGHT ,
L : LEFT , R : RIGHT ,
T : TOP , TL : TOP_LEFT , TR : TOP_RIGHT
} ;
var defaultA:String = default_align || StageAlign.CENTER ;
var a:String = align.toString().toUpperCase() ;
return (aligns[a]) ? aligns[a] : defaultA ;
}
// ----o Constant
static private var _constant:Function = Constant ;
static private var _init:Boolean = __initConstants() ;
static private function __initConstants():Boolean {
var props:Array = [
"BOTTOM" , "BOTTOM_LEFT" , "BOTTOM_RIGHT" , "LEFT" , "RIGHT" ,
"TOP" , "TOP_LEFT" , "TOP_RIGHT"
] ;
return _constant.setConstants(StageAlign, props) ;
}
}
Mais c'est un peu lourd... le coup de déclarer à la fin une fonction d'initialisation etc....
En fin de compte est ce vraiment utile ? je discutais de cela avec Shaoken la dernière fois et au final faut voir si on veut un code super protégé ou léger ?
Vive l'AS3 en bref qui permet de se prendre moins la tête là dessus lol
EKA+
ben ouais, le fait que l'AS2 reste du prototype au final
ce qui compte, c'est à l'écriture, à la compilation, la vérification des types et tout
mais faut avouer qu'une petite protection, pourquoi pas
c'est vrai que j'me suis jamais pris la tête avec les constantes
déjà avec la convention d'écriture, à chaque fois que j'ai des majuscules dans les variables, je modifie jamais
pour moi c'est surtout l'avantage du typage qui est important
mais c'est vrai que la technique est sympa
on peut pas faire CryptMode.MD5 = "pipi" directement
l'AS3 aussi cela reste du prototype... A première vue quand on tape const lors de la compilation cela met un genre de ASSetPropFlags en 7 directement sur la variable non ? Faudrait que je regarde ce qui remplace ASSetPropFlags (ou pas ...) en AS3 d'ailleurs ?
EKA+
heu nan, avec l'AVM2, ca va changer
ils ont quand meme pas fait tout ca pour garder les prototypes
c'est ce que j'espère
bah les prototypes sont pas près de disparaitre
Regarde la classe Object dans la doc AS3
Tu verras même en fouillant un peu dans l'install de flexbuilder que les prototypes sont utilisés :

package flash.errors{
public dynamic class IllegalOperationError extends Error {
function IllegalOperationError(message = "") {
super(message);
}
...
IllegalOperationError.prototype.name = "IllegalOperationError"
}
Je te conseille d'aller voir sur le newsgroup de Flexcodeurs l'article : [AS3] tout ce que vous avez toujours voullu savoir sur AS3
EKA+
ya pas version html ?
si mais c'est récent la connexion au googlegroup donc ce Post là n'est pas dans les archives :
- http://www.burrrn.com/projects/FCNG.html
- http://groups.google.com/group/FCNG
En fait je préfère la version NG que HTML lol
EKA+
Tiens.. une autre discussion intéressante sur l'utilisation du prototype en AS3 : (flexcodeurs) [AS3] augmenter les core objects
eka laisse moi te dire que tu es un p#@~!! de gros floodeur
: partout où je vais sur le net je vois tes classes disséminées une à une est-ce un jeu de piste ?
tu ne pourrais pas sortir tes trucs une bonne foi pour toutes sur ton blog maintenant que t'en a un.
sinon merci lalex pour ce trick j'aime bien ;).
françois.
Floodeur de quoi ? je peux savoir ? je discute sur le sujet de ce message non ? lol Sinon j'ai mal compris le but de mettre des balises code actionscript et le pourquoi de commentaires sur un blog ^_^
Sinon t'inquiète cela va venir sur mon blog pour laisser mon framework et les classes qui vont avec
et forcément c'est grace à des discussions comme ici que j'avance dessus hein 
http://live.burrrn.com/wiki/VEGAS
Mais j'attends d'avoir une version 1 stable
EKA+
t'as pas le sentiment que poster une classe (et encore si ce n'était qu'une !!) d'une 60aine de lignes plus encore 60 lignes de commentaires et de licenses (soit déjà 120 lignes) n'a peut être pas forcément sa place dans un comment de blogs ... tu pourrais te contenter d'en parler et mettre des liens vers tes classes pour illustrer tes propos ? ou encore faire des billets des trackbacks ... autre chose quoi
bonnes fêtes à tous
Tu vois une licence dans mes commentaires à quel endroit exactement ?
Je voulais juste illustrer que je trouvais compliqué de faire une constante en AS2...
Excuse moi d'en faire trop hein et d'avoir fait un copier/coller... là dessus je m'en excuse c’est certain.
Ensuite, excuse moi d'essayer de réagir au sujet du post et d'apporter un peu ma modeste contribution à la communauté. Forcément à ce que je vois, il semblerait à tes dires n'en a pas du tout besoin ... et bien alors dommage ^_^
Et surtout excuse moi contrairement à toi de m’intéresser plus au fond qu'à la forme de ce message…
Je pense par contre plus sérieusement que là c'est toi qui est déplacé au niveau de ta réponse... et que tu cherches la petite bête encore une fois... Tu devrais avoir autre chose à faire la veille de Noël non ?
Mais bon... comme on dit : trop bon, trop con…
Je me demande vraiment ce que l'on peut avoir dans la tête quand on vient faire des remarques de ce type ? Sachant que pour le moment je n'ai pas eu de mail de Lalex pour me dire que mes commentaires sont déplacés et dans tous les cas ill est libre de virer mes commentaires si il pense que c'est du "flood de base" .... Et sachant qu’on se connaît un peu il n’y aura pas de problème si il me faisait la réflexion là-dessus par mail.... contrairement à toi que je ne connais ni d’ADAM ni d’EVE…. et là dans ce contexte je ne l'accepte pas.
Donc si tu es là pour faire le lèche botte ... "OUAIH COOL SUPER TON ARTICLE.... et que pour le reste dès que quelqu'un essai de se lancer dans une conversation dans un espace réservé à cela (à ce que je crois) ; forcément avec moi tu es mal tombé....
Désolé Lalex de m’emporter encore une fois et si tu veux effacer ce message n’hésite pas mais là c’est affolant de voir cela.
EKA+
bon euh joyeux noel à tout le monde
lalex:
"Impossible de rajouter des constantes non-prévues au runtime, du fait du constructeur privé" etc.
oui c'est clean niveau du typage a la compilation, mais apres le code peu quand meme etre modifié au runtime (cf autres comments).
neolao:
"ils ont quand meme pas fait tout ca pour garder les prototypes
c'est ce que j'espère"
bah si justement, maintenant ils suivent le standard ECMAScript (et pas que celui-là d'ailleurs),
et tout ce qui va avec: philosophie object-based, prototype, traits, etc.
et vraiment c'est pas un mal amha
eka:
si tu veux vraiment protéger utilise plutot
_global.ASSetPropFlags(o, props, 7, 7) ;
en mettant 7 sur le dernier param
si quelqu'un veut unlocker en faisant un
_global.ASSetPropFlags(o, props, 0, 1) ;
ta prop sera toujours protégée contre le delete et l'override
et euh pour ta maniere de definir des enums...arghhhh mais beurk
ca fait un peu trop de choses a definir pour ce qui devrait etre une simple enumeration amha.
Donc pour reprendre quand meme le sujet du post,
en appliquant le standard ECMAScript donc, dans un but de protection de variables (const, static, ou autre.)
voir ECMA-262 property attributes specification (chapter 8.6.1 , PDF p38/188).
Et merci donc AS d'avoir ASSetPropFlags qui nous permet justement de definir de modifier l'attribut d'une var en tant que readOnly et dontDelete, cad qu'on ne pourra pas changer ni son type ni sa valeur que ce soit a la compilation ET au runtime.
sinon aussi une autre solution est de ne pas utiliser du tout les enums :).
interface IHashAlgorithm
Et si plus tard on veut rajouter d'autres class de hash il n'y aura pas de switch a modifier, polymorphism is good :D. Mais bon meme si ca presente des avantages, il y a aussi des inconvenients. Apres tout dépends bien sur de ce qu'on cherche a proteger (valeurs possibles, type check seulement a la compilation), ou protection absolue meme au runtime (cad impossible de remplacer la methode de hash parmis un set de methodes données). Sinon pour continuer sur les enums, faire aussi attention à cela: http://blogs.msdn.com/peterhal/archive/2005/08/01/446357.aspx des fois avoir un type d'enum autre qu'un type primitif ca peut trop compliquer les choses{
public function encrypt( message:String ):String;
}
class MD5 implements IHashAlgorithm
{
function MD5()
{
}
public function encrypt( message:String ):String
{
return "MD5 hash";
}
}
class SHA1 implements IHashAlgorithm
{
function SHA1()
{
}
public function encrypt( message:String ):String
{
return "SHA1 hash";
}
}
class Crypter
{
public static function encrypt( message:String, hash:IHashAlgorithm ):String
{
if( hash == null )
{
hash = MD5; //default
}
var hashObj:IHashAlgorithm = new hash();
return hashObj.encrypt( message );
}
}
switch( StageAlign ){
//...
case StageAlign.left | StageAlign.top:
//dans un cas comme ca des enum int sont plus pratiques par ex
break;
//...
}
bref, juste pour dire que attention a comment on definit ses enums, sur le long terme ca peut vraiment bloquer les choses dans le design du code et forcer a refaire trop de modif sur des simples paramettres.
@zwetan :
Encore ce problème de compatibilité avec AS3.... car en fait je préfère l'utilisation des | dans le cas de figure que tu viens de citer au dessus.
Sinon oui tu as raison pour le ASSetPropFlags je le mettrais en 7,7 mais par contre je me demande pourquoi Macromedia n'a pas laissé une porte en AS2 en permettant par exemple d'utiliser directement le ASSetPropFlags en suivant dans la déclaration des propriétés dans une classe AS2.
EKA+
Ah oui sinon et comme cela ?
class vegas.display.StageAlign extends String {Petit test ensuite dans flash :private function StageAlign() {
//
}
static public var BOTTOM:String = "B" ;
static public var BOTTOM_LEFT:String = "BL" ;
static public var BOTTOM_RIGHT:String = "BR" ;
static public var CENTER:String = "" ;
static public var LEFT:String = "L" ;
static public var RIGHT:String = "R" ;
static public var TOP:String = "T" ;
static public var TOP_LEFT:String = "TL" ;
static public var TOP_RIGHT:String = "TR" ;
static private var __CONS__ = _global.ASSetPropFlags(StageAlign, null , 7, 7) ;
}
import vegas.display.StageAlign ;trace("- " + StageAlign.TOP_LEFT) ;
StageAlign.TOP_LEFT = "coucou" ;
trace("- " + StageAlign.TOP_LEFT) ;
trace("> " + StageAlign.TOP_RIGHT) ;
StageAlign.TOP_RIGHT = "hello" ;
trace("> " + StageAlign.TOP_RIGHT) ;
cela fait ajouter une variable statique dans la classe mais bon ... cela semble fonctionner et c'est plus simple à mon avis non ?

EKA+
Bah perso faisant presque pareil j ai rien a redire :P.
les 2 seules differences:
- je n'herite meme pas de String
- j'utilise __ASPF__ au lieu de __CONS__
mais bon StageAlign est un cas special, vue que justement on veut des String,
en general je n'utilise que des int/Number bien plus pratique amha (op bitwise, classement par categorie en notation hex, etc.)
Alors oui c'est sur dans le cas d'un enum comme CryptMode, il ne sera pas typé CryptMode mais Number, mais perso ce qui m'interesse surtout c'est le nommage du enum (et la protection ASPF)
class CryptMode{
public static var NONE:Number = 0;
//public static var CRC32:Number = 0x001
//public static var ELF:Number = 0x002
//public static var MD4:Number = 0x010;
public static var MD5:Number = 0x020;
public static var SHA1:Number = 0x100;
static private var __ASPF__ = _global.ASSetPropFlags(CryptMode, null , 7, 7) ;
}
class Crypter {
private var _cryptMode:Array;
private var _select:Number;
_cryptMode[ CryptMode.NONE ] = new NoHash();
_cryptMode[ CryptMode.MD5 ] = new MD5();
_cryptMode[ CryptMode.SHA1 ] = new SHA1();
function Crypter(mode:Number) {
_select = mode;
}
function encrypt(s:String):String
{
if( _cryptMode[ _select ] )
{
return _cryptMode[ _select ].encrypt( s );
}
return _cryptMode[ CryptMode.NONE ].encrypt();
}
}
}
enfin dans l'idée quoi..
l'héritage de String au dessus c'est une erreur vu que j'étais dans l'élan de l'idée lol ^_^ et je pense que je vais te piquer ta notation __ASPF__ si cela te dérange pas (faudrait pas qu'on me dise aprés que je te plagie... lol)
EKA+
c'est vrai, j'y avais pas pensé, il y a la stratégie aussi
sinon, ca veut dire quoi ASPF ?
et dans le dernier exemple, ca me gène un peu le remplissage de _cryptMode
dans l'exemple, la logique c'es de choisir le mode dans le constructeur, c'est là que j'aurai créé l'instance de ce qu'il me faut
voire 2 instances si on compte le NoHash
ASSetPropFlags = ASPF
Oui, mais en général je table sur une utilisation "propre" du code... Evidemment, il est toujours possible avec l'opérateur crochets d'aller faire un peu ce qu'on veut!
++ ^^
De toutes façons, dans l'absolu, il suffit de passer un objet anonyme à un méthode pour qu'il ne tienne plus compte du typage... :p
Ralala et dire que certains ont droit à des typedef, struct, const, inline functions, reféfinitaions des opérateurs, déf de types primitifs, etc ... et que nous on galère comme des chiens pour protégrer en écriture une pauvre variable (et on y arrive même pas) !
On y arrive avec le ASSetPropFlags non ?
Sinon c'est clair qu'il manque encore des petites choses en ActionScript
Mais cela va venir je pense... l'AS3 marque déjà cette évolution 
Instructif comme discussion
Juste 2 choses :
- comme Zwetan pour l'utilisation des int/Numbers plutôt que des strings (plus efficace, souple, etc),
- je trouve que l'AS2 (et surtout l'AS3) n'a pas trop à envier des autres langages (à part les enums) -- félicitons nous plutôt de sa flexibilité !
Fil des commentaires de ce billet