Composition et __resolve : simplifiez vous la composition
Par -Alexandre LEGOUT aka LAlex- le vendredi, juillet 30 2004, 16:32 - AS2 - Lien permanent
En train de coder un gestionnaire de positionnement pour des clips sur la scène, je me vois confronté au problême bien connu du centrage des clips. En effet, les coordonnées _x et _y ne sont pas forcément celles du coin supérieur gauche du clip. Le canadien Stéphan Guénette s'est déjà penché sur cet épineux problême, et propose une solution bien pratique sur son blog ... ![]()
Seulement, cette solution me pose quelques problêmes, tout d'abord parce qu'il s'agit d'une manipulation de prototypes, bien peu conseillée en AS2, et ensuite parce qu'à chaque accés à une propriété de positionnement, il s'effectue un appel à la méthode getBounds() ... Je ne me suis pas encore penché sur le second problême, mais concernant le premier, j'ai trouvé une petite astuce bien pratique pour accéder facilement aux propriétés d'un MovieClip membre d'une classe, et ce sans utiliser l'héritage.
Il s'agit en fait d'utiliser la méthode non documentée __resolve(), dont voici mon utilisation :dynamic class net.lalex.movieclip.SuperClip {
Comme vous le constatez, __resolve() permet d'intercepter les appels à des membres d'une classe qui n'existent pas, et d'en faire un peu ce que l'on veut. Le seul problême est que l'on ne peut pas accéder en écriture aux propriétés du clip. Comme il s'agit là d'une classe native, il faut donc ne pas oublier de créer les accesseurs pour modifier les propriétés (setX, setY, setRotation, etc...) ... mais si l'on s'en tient à l'utilisation des accesseurs pour la manipulation de propriétés lors du développement de classes "maisons", ce qui est bien plus conseillé en POO, cela fonctionne parfaitement !
// Clip ciblé
private var _targetMC:MovieClip;
// Constructeur
public function SuperClip(mc:MovieClip) {
_targetMC = mc;
}
// Redirige les requêtes non existantes vers le clip
// contenu dans la propriété _targetMC
public function __resolve(p:String) {
// Si c'est une méthode, on l'applique au clip lui-même
if (typeof _targetMC[p] == "function") {
return function() {
return _targetMC[p].apply(_targetMC, arguments);
}
// Sinon, on retourne la propriété
} else {
return _targetMC[p];
}
}
}
Voici un exemple d'utilisation :import net.lalex.movieclip.SuperClip;
// Création de l'instance de SuperClip
var monClip:SuperClip = new SuperClip(_root.monCarre);
// Accés à une méthode du clip contenu dans monClip
// donc, une méthode de _root.monCarre
// Ici, il s'agit de mettre monCarre au dessus des tous les autres
monClip.swapDepths(monClip._parent.getNextHighestDepth());
Evidemment, ca tient tout autant de la bidouille que la solution avec les prototypes, mais je préfère malgré tout avoir une "vraie" classe ! ![]()
Commentaires
Un grand merci à toi, je connaissais pas du tout cette petite fonction...
Ca va pas mal simplifier certaines choses lors des accès aux MovieClips....disons que ça sera plus transparent.....
Ah lala, les fonctions non documentées.....toujours pareil.....
Dommage que ça ne fonctionne qu'en lecture
@+ et merci...
A noter qu'il faut déclarer la classe comme étant dynamic obligatoirement, si on ne veut pas avoir de problème avec le "type checking" du compilo !
merci
!
je suis content ca faisaint un petit moment que je me demandais ce que faisait __resolve
par contre est ce que le fait que la fonction soit non documenter implique le fait qu'elle puisse disparaitre ou pas tant que ca (un peu a la maniere de ASBroadCaster) ?
Hello

ASBroadCaster... dans flash MX 2004 tu as la classe mx.transitions.BroadcasterMX à la place
Sinon pour ma part je me suis fait une classe un peu spéciale qui elle utilise l'héritage de MovieClip et qui me permet de gérer via une propriété R/W align le positionnement de mes clips et j'utilise alors 2 nouvelles propriétés R/W pour les positions x et y
Cela alourdi pas tant que cela mes clips et c'est plus propre je trouve 

bye
yoy > En effet, il se peut que __resolve vienne à disparaitre ...
Mais cette instruction était utilisée dans des composants v1. A moins que Macromedia veuille se couper de tous les sites encore fait en Flash MX, c'est donc peu probable ! 
AsBroadcaster n'a pas disparue, c'est juste que le premier "s" est en minuscule. Il vaut mieux utiliser celle-ci plutôt que BroadcasterMX, cette deuxième étant codée en AS, et donc moins performante ... :o
La classe AsBroadcaster est elle directement compilée dans le player !
Merci lalex et eka pour ces précisions... c'est exactement ce que je voulais savoir
... en tout cas merci pour l'info je vais garder le AsBroadCaster dans un coin de ma tete ... hihi
Pour ce qui etait de asbroadcaster, c'etait l'exemple pour illustrer le fait que cest une fonction non doc mais qui peut pas diparaitre
il faut faire attention avec l'utilisation du __resolve
- ne pas oublier un acces au _global
- utiliser hasOwnProperty pour eviter les loop infinis
cheminement d'un acces de membre (propriete ou methode):
- check au niveau de l'instance (ex: monInstance.member )
- check au niveau du constructeur de l'instance ( ex: monInstance.__proto__.member )
- check dans la chaine de prototype (ex: monInstance.__proto__.__proto__.member )
- etc... jusqu'a temps d'arriver en fin de chaine de prototype ( cad le __proto__ == null )
- check au niveau de _global ( ex: _global.member )
le __resolve agit au niveau de la fin de chaine de prototype,
si on ne prends pas soin de verifier si le membre existe en _global, on perd l'acces au _global a cause du __resolve.
exemple simple qui montre le non appel a _global:
_global.test = "hello world";solution:__resolve = function( member )
{
trace( member + " not found" );
}
trace( test ); // on devrait obtenir "hello world"
_global.hasOwnProperty = Object.hasOwnProperty;de plus il faut aussi faire attention a comment on appelle le code a l'interieur du __resolve, on peut aussi bien appliquer l'appel sur le scope de l'appelant que sur celui de l'appelé_global.test = "hello world";
__resolve = function( member )
{
if( _global.hasOwnProperty( member ) )
{
return _global[member];
}
trace( member + " not found" );
}
trace( test ); // on obtient bien "hello world"
__resolve = function( member )et{
return function()
{
return target.apply( target, arguments ); //scope de l'appelé
}
}
__resolve = function( member )les 2 sont possibles et valides, tout depends de ce que l'on veut faire ;). Pour ce qui est du probleme avec AS2, moi je dis qu'il n'y en a pas, enfin tout depends de comment on se place par rapport a ECMAscript: - soit on choisit de faire du JAVA avec ECMAscript, et forcément __resolve va etre abherant et on va preferer la solution du MVC (Model-View-Controller) sans chercher a voir ou comprendre plus loin. - soit on choisit d'utiliser et de comprendre la nature de ECMAscript et on utilise les fonctionnalités de delegation qui sont d'office dans le langage. Dans ce cas on peut voir __resolve comme un équivalent du prototype mais qui permet de choisir le chemin de delegation. Beaucoup de gens qui conseille le MVC dans flash, ignore le concept de visual proxy http://www.javaworld.com/javaworld/jw-09-1999/jw-09-toolbox.html Et quand on y regarde de plus pres, le visual proxy est bpc mieux adapté et pratique a du ECMAscript (surtout si on plus on dipose d'un __resolve). voir le thread sur FCNG du 25/02/2004: "[FMX] essai de solution pour relier une class a un clip" news://flashcodeurs.dyndns.org/flashcodeurs où on peut trouver ce code source: (qui n;est pas parfait mais qui illustre bien ;)){
return function()
{
return target.apply( this, arguments ); //scope de l'appelant
}
}
/* Class ResolverProxyAllow to link an object with another objet using __resolve
instead of ASBroadcaster, EventBroadcaster, EventDispatcher, etc...
ATTN: this a 1 to 1 relationship
EventBroadcaster -> 1 to * + unidirectional
ResolverProxy -> 1 to 1 + unidirectional or bidirectional
NOTE: this can be used to connect a "Model" object
to a "View" object as an alternative to
"Model-View-Controller" or "visual proxy".
ex1:
myModel = new Model();
_root.createView( "myView" );
myView.proxy = myModel;
myModel.proxy = myView;
ex2:
myModel = new Model();
_root.createView( "myView" );
myView.link( myModel );
the View and the Model share their methods
and properties as they were only one object.
*/
_global.ResolverProxy = function( /*reference*/ proxy )
{
this._proxy = proxy;
ASSetPropFlags( this, "_proxy", 1, 1 );
this.addProperty( "proxy", this.getProxy, this.setProxy );
}
/* Method getClassName
*/
ResolverProxy.prototype.getClassName = function()
{
return "ResolverProxy";
}
ASSetPropFlags( ResolverProxy.prototype, "getClassName", 1, 1 );
/* Method link
create a bidirectional link between an object and this instance
this <--> object
*/
ResolverProxy.prototype.link = function( /*reference*/ linkedProxy )
{
linkedProxy.proxy = this;
this.proxy = linkedProxy;
}
ASSetPropFlags( ResolverProxy.prototype, "link", 1, 1 );
/* Setter setProxy
create a unidirectional link between an object and this instance
this --> object
*/
ResolverProxy.prototype.setProxy = function( /*reference*/ proxy )
{
this._proxy = proxy;
}
ASSetPropFlags( ResolverProxy.prototype, "setProxy", 1, 1 );
/* Getter getProxy
*/
ResolverProxy.prototype.getProxy = function()
{
return this._proxy;
}
ASSetPropFlags( ResolverProxy.prototype, "getProxy", 1, 1 );
/* Internal Method __resolve
Allow to establish a scope link between
this object scope and the proxy object scope.
*/
ResolverProxy.prototype.__resolve = function( /*String*/ name )
{
if( this.proxy == null )
{
/* no proxy defined */
return;
}
/* DON'T TOUCH THIS !!!
not found in the instance
*/
if( !this.proxy.hasOwnProperty( name ) )
{
/* not found in the constructor prototype */
if( this.proxy.__proto__[name] == undefined )
{
/* to prevent 256 levels of recursion eg. infinite loop */
return;
}
}
if( typeof(this.proxy[name]) == "function" )
{
/* method link */
return function()
{
return this.proxy[name].apply( this.proxy, arguments );
}
}
else
{
/* property link */
return this.proxy[name];
}
}
ASSetPropFlags( ResolverProxy.prototype, "__resolve", 1, 1 );
/* Static Method initialize
add resolverProxy capability to a target object.
*/
ResolverProxy.initialize = function( /*reference*/ target )
{
var toHide;
target._proxy = null;
target.link = ResolverProxy.prototype.link;
target.getProxy = ResolverProxy.prototype.getProxy;
target.setProxy = ResolverProxy.prototype.setProxy;
target.__resolve = ResolverProxy.prototype.__resolve;
target.addProperty( "proxy", target.getProxy, target.setProxy );
toHide = [ "_proxy", "link", "getProxy", "setProxy", "__resolve" ];
ASSetPropFlags( target, toHide, 1, 1 );
}
zwetan > En effet, il faut que je teste le _global. Je n'en avait pas besoin jusque là, étant donné que je faisais une utilisation systématique du this ou du _global pour mes ciblages ..; Mais je me suis décidé il y a peu à éliminer le this à l'intérieur de mes classes ...
Par contre, concernant le hasOwnProperty dans ce cas précis, je pense qu'il n'a pas à être utilisé ici, car je veux pouvior accéder aux méthodes et propriétés de mon _targetMC, qu'elles soient héritées ou non !
Je vais jeter un coup d'oeil au VisualProxy de ce pas ! ^^
Je comprends rien à ce que vous racontez :p
lalex >
le hasOwnProperty est surtout utile si on fait interagir 2 scope d'objet l'un vers l'autre
cad:
A.__resolve qui point vers B
et
B.__resolve qui point vers A
le hasOWnProperty est le seul moyen de tester l'existence d'un membre sans faire appel a __resolve
on est obligé de cibler le _global dans les class AS2, ou alors il faut aller modifier le fichier toplevel.as dans son classpath
quand a l'utilisation du this, meme en JAVA il y a des cas où on ne peut pas faire sans
apres les gens sont libre de se compliquer la vie comme ils veullent
Arf, je connaissais pas ce fichier toplevel.as ... :o
Sinon, concernant le _global, tout d'abbord je ne pense pas que ce soit une bonne pratique que d'utiliser des variables globales en AS2, et ensuite, à partir du moment ou tous les appels à des variables et/ou fonctions globales sont précédés de leur ciblage _global. ca ne pose pas de problêmes à priori ... Mais l'utiliser "au cas où" ne fait pas de mal !
Au fait, concernant ton commentaire précédent, je me demande si __constructor__ n'est pas incrusté quelque part dans la liste des scopes, ne serait-ce que pour les appels aux propriétés/méthodes statiques, dont l'équivalent en AS1 est en fait une méthode/propriété contenué dans la fonction constructeur ... :o
Evidemment, le this est parfois obligatoire, ne serait-ce que pour transmettre l'objet courant en tant que paramètre à une méthode :
Mouse.addListener(this);++ ^^
toplevel, c'est le super trick super OO ala JAVA (oui c'est tres ironique) que MM a trouvé pour contourner les appels de ce qui est défini en _global (pour que le compilo ne se prenne pas les pieds dans le tapis).
Pour ce qui est des var en _global, quand c'est pour définir des namespace, des class, des fonctions génériques du meme niveau que un ParseInt ou autre, désolé c'est utile.
pour info ce code AS2:
class Totocompile ca en AS1: (dans un symbol MC nommé __Package.Toto){
function Toto()
{
}
}
#initclipalors que si on le codait en AS1 ca compilerait comme ca:if (!_global.Toto) {
var _local1 = function () {
};
_global.Toto = _local1;
var _local2 = _local1.prototype;
(ASSetPropFlags(_global.Toto.prototype, null, 1));// not popped
}
#endinitclip
_global.Toto = function () {};
dans les 2 cas le _global est utilisé de toute manière.
ECMAscript a obligatoirement un scope global où sont definis les objets par defauts, aussi bien les core object (String, Array, etc..) que les objets propre a l'environnement de flash (Sound, LoadVar etc..) et c'est tout a fait une bonne pratique OO de définir ses propre objets en _global.
La fameuse phrase "bla bla ...c'est une mauvaise pratique d'utiliser des var globales ...bla bla" c'est comme le coup du pattern Singleton qu'on implémente a coup de dfinition de class et de getInstance(), c'est a se demander si les gens comprennent qu'ils parlent de ces choses là dans le contexte d'un langage basé sur les prototypes (la nature du langage pas juste le bete mot "prototype").
Je sais pas si l'effet recherché est de faire sérieux en utilisant une syntaxe à classe, perso je vois des gens qui se prennent la tete pour humm...des conneries, et pour le Singleton j'en rigole encore :D.
(hint: dans un pattern Singleton c'est justement là où le this prends tout son intéret)
On aura compris que tu n'aimes pas AS2, tu nous l'a suffisamment répété ... :\ Mais là, ca devient quand-même assez lourd, d'avoir dans chacun de tes commentaires quelque chose qui ressemble à "BOUUUUUH ! AS2 C'EST NUUUUUUUUUUUUL !!!" ... :\
Concernant le _global, je pensais déjà que c'était une mauvaise pratique en AS1 (excepté pour les définitions de classes, mais on avait pas le choix), et c'est un choix purement personnel que de ne pas l'utiliser ...
Concernant le pattern Singleton, je ne vois pas quel est le problème de la définition de classe et de getInstance() ... C'est la définition même de ce pattern, et à partir du moment où tu décides d'utiliser la syntaxe AS2, il n'y a pas d'autres manières de l'implémenter ... :o
Dans tous les cas
l'AS2 reste plus souple non ? c'est pas le plus important ?
et l'AS1 .. sérieux j'aime aussi mais cela me fait perdre + de temps 

Mettre des prototypes dans de l'AS2 pour ma part cela me dérange pas tant que c'est fait dans le bien de mes applications.
Maintenant je considère que tant qu'on sait comment fonctionne flash niveau de ces prototypes ... faire de l'AS2 reste la meilleure solution de faire des gros projets sans se prendre trop la tête, surtout quand on bosse à plusieurs.
J'aime l'AS2
A+
moi je te dis simplement que AS2 il utilise _global de la meme maniere que AS1 que tu veuilles le voir ou non, tu peux t'enerver tout seul, me faire dire des choses que je n'ai pas dites, ca ne change strictement rien.
Ce qui est lourd c'est de voulloir faire et penser JAVA avec de l'ECMAscript, et de toute suite perdre son sang froid des que quelqu'un ne dit pas comme toi ou comme tous les autres.
Pour le Singleton en ECMAscript c'est tres simple
_global.monSingleton = new Object();monSingleton.maMethod = function()
{
...
this.maVar //this pour pointer sur le scope du singleton justement
}
http://c2.com/cgi/wiki?PrototypeBasedProgramming
"A few platypi (like the SingletonPattern) completely disappear. If you want there to be only one of a particular kind of object, then... only make one of them. If you don't want it to be able to be copied, then don't give it a "copy" method."
Un pattern n'est qu'un pattern, on est pas obligé d'implémenter le Singleton exactement de la meme maniere dans tous les langages, il ne faut pas oublier de tenir compte de la nature du langage utilisé
http://c2.com/cgi/wiki?SingletonPattern
un Singleton en Python ne s'implemente pas de la meme maniere que en JAVA ou en C++, et donc c'est la meme chose pour ECMAscript, il faut tenir compte de la nature du langage.
Oublier que AS2 reste basé sur ECMAscript, un langage basé sur les prototype, est une grosse erreure selon moi, apres chacu nfait ce qu'il veut et on peut toujours apprendre de ses erreures.
JE SUIS D'ACCORD AVEC TOI : IL NE FAUT PAS OUBLIER QUE AS2 RESTE DE L'AS1 !!! (dedieu, je l'ai suffisamment répété en plus) Seulement, a partir du moment ou l'on utilise une syntaxe class-based, autant utiliser aussi les usages de cette syntaxe. Ceux qui ne le veulent pas resteront en AS1, et chacun chez soi : mais aller voir l'autre pour lui dire que ce qu'il utilise est systématiquement la mauvaise méthode, ca n'a auncun interêt ! :\
Etant donné que tu ne supportes pas l'AS2, je te propose à ce moment là de ne plus réagir sur les tickets qui abordent l'AS2, ca me parait plus simple ...
++ ^^
on doit pas parler dans le meme contexte ...decidement :S
je ne dis pas de ne pas utiliser AS2, ni meme de ne pas utiliser une syntaxe class-based.
je dis que de part sa nature ActionScript, que ce soit en v1 ou v2, reste basé sur ECMAscript
et que cela donc implique une maniere de penser le code differente que si on programmait avec JAVA ou C#.
pas parce que c'est du flash, mais au contraire de JAVA et C# qui sont class-based
ECMAscript lui est prototype-based, et là je ne parle pas du mot clef "prototype" je parle du comportement du langage, cad:
- en prototype-based (ECMAscript), la "class" (le constructeur) est un objet que l'on copie pour créer une instance (un objet), ce qu'on appelle "class" que l'on declare en AS1 ou AS2 est du type Object.
- en class-based (JAVA), la class est une description abstraite d'un objet qui servira a creer une instance (un objet) mais la class n'est pas du tout du type Object, une class n'est pas du tout un type.
c'est fondamentalement TRES different!
En ECMAscript, la fonction constructeur ne crée pas un type spécifique, elle crées tout simplement un objet point ligne.
En JAVA, la class definit l'abstraction d'un type et des que l'on crée une instance en fonction de celle-ci on crée donc une instance de type spécifique, c'est d'ailleurs pour cette raison que on peut faire ce qu'on appelle du "code reflexion"et c'est exactewment pourquoi on n'a pas du code reflexion par defaut en ECMAscript.
http://c2.com/cgi/wiki?ClassesVsPrototypes
"the two ways of organizing objects are incompatible - you have classes, you have prototypes, but you got to choose."
-> les deux manières d'organiser les objets sont incompatibles - vous avez les classes d'un coté, vous avez les prototype de l'autre, mais vous devez choisir.
D'où ma remarque dans un autre commentaire sur les Singleton,
en ECMAscript comme on est directement au contact du type objet on peut directement
déclarer un Singleton simplement en créant une instance du type objet, pas besoin de passer
par une fonction constructeur ("class") pour créer cette instance unique, alors que en JAVA et bien ils n'ont pas d'autre moyen que de passer par une class si ilsveullent créer un objet vue que les class en JAVA ne sont pas du tout du type objet.
Et c'est comme ca pour des tonnes de comportement du langage ECMAscript,
autre exemple les generiques, si on regarde vite fait dans les specifications ECMA-262
on verra des choses comme ca:
"15.4.4.4 Array.prototype.concat( [item1 [, item2 [, ...]]]
[description de la methode]
NOTE
the concat function is intentionally generic; it does not require that its this value be an Array object.
Therefore it can be transfered to other kinds of objects for use as a method.
Wether the concat function can be applied sucessfully to a host is implementation-dependent.
"
un generique c'est pas dur, c'est une fonction/methode/propriete/etc... qui marche de la meme maniere sur les valeurs de differents types d'objet.
ex:
String.prototype.concat = Array.prototype.concat;
ce qui permettrait de faire des concatenation de String de la meme maniere qu'on faitd es concatenation d'Array (un peu a la maniere du String.Builder.Append() de C#).
C'est un comportement qui existe par defaut dans ECMAscript (1999) qui est tres utile et qui est totalement dans la philosophie d'un langage dynamique.
Les generiques n'existeront dans C# que dans la v2 du .NET framework (2005)
http://research.microsoft.com/projects/clrgen/
ils n'ont ete introduits dans JAVA que dans le JDK v1.5 (2002)
http://java.sun.com/developer/technicalArticles/releases/generics/
plus d'info sur pourquoi les langages class-based ont besoins des generiques:
http://c2.com/cgi/wiki?GenericsVsSubtyping
Quand je rale sur AS2, c'est pas parce que c'est de la syntax class-based ou juste que le nom AS2 ne me plait pas, je rale sur ce genre d'utilisation du langage que le compilo MX 2004 empeche justement avec la syntaxe AS2.
ex pour utiliser des generiques:
class Totoet d'un point de vue pratique{
var load:Function = LoadVars.prototype.load; //ca plante
//on est obligé de faire comme ca
function load( filepath:String )
{
return LoadVars.prototype.load.apply( this, filepath ); // bravo, super pratique!
}
_global.Toto = function(){
}
Toto.prototype.load = LoadVars.prototype.load; //ca arche tres bien
je critique pas la syntaxe AS2, je critique le fait que AS2 empeche d'utiliser des comportements de programmation évolués inhérent a la nature de ECMAscript !
pour les Singleton c'est le meme probleme.
je dois te corrgier sur certains points zwetan

en Java, les classes sont de type java.lang.Classe
et puis les Generics de Java Tiger ne sont pas du tout ce que tu mentionnes ci-dessus. C'est plutôt un moyen de forcer une collection d'accepter un typer précis d'objet. Ce qui permet d'éviter de caster à chaque itération
PS -> au passage, c'est Java et non JAVA... J'ai l'impression que tu cries à chaque fois que tu parles de Java
@++
alors dans l'ordre:
- oui le java.lang.class existe mais ce n'est pas un type instanciable, bon je vais etre encore plus precis sinon pareil on va focaliser sur la petit chtouille expliquée vite fait (plutot que le probleme de fond ECMAscript !== JAVA).
Au sens strict du terme, le java.lang.class ne peut etre construit et donc géré que par la JVM, un dev ne peut pas instancier ce type, cad:
Class toto = new java.lang.Class();
ce n'est pas possible.
- pour les generics, je n'en parle pas au niveau de JAVA, j'en parle au niveau de ECMAscript, et d'ailleurs je ne vois pas où tu vois que je donne une définition des generics pour JAVA ?
oui dans le contexte de JAVA qui est class-based et staticlly typed.
Mais dans le contexte de ECMAscript qui est prototype-based et dynamically typed, et c'est de ca dont je parle, aborder les genrics comme dans JAVA ca n'a aucun sens.
Si C# ou JAVA ont besoin des generics c'est justement a cause du typage (statically typed), car ca les force souvent a faire du boxing/unboxing pour obtenir le bon type.
En plus clair, ca les fait chier de devoir faire du boxing/unboxing juste pour verifier que le type est correct, les generics ca leur permet de ne pas devoir s'occuper de ca et d'aller plus vite, bref le langage lui-meme avec les generics s'occupe du bon casting du type et ils ne sont pas obligé de le faire ala main.
(c'est dingue bientot on parlera plus de JAVA que de AS si ca continue)
Dans le cas de ECMAscript (meme avec AS2) on est pas du tout statically typed, le langage lui-meme s'occupe deja de gerer les autocast
ex:
toto = 5 + "hello"; //autocast en string
autre ex:
toto = new String("hello world");
titi = "hello world";
tutu = String( "hello world");
le type est le meme, et pourtant ce sont 3 choses bien différentes.
L'importance du coté des generiques avec ECMAscript c'est que dans ce langage le type est caracterisé par la signature de l'objet et que les generiques sont la logique de pouvoir appliquer un code en dehors de la consideration de la signature de l'objet, mais si on peut faire ca c'est justement parce que les typage est dynamique, on peut nous dans bcp de cas se fouttre du typage.
pas JAVA, pas C#.
note: JAVA au lieu de Java, vieille habitude pour mettre dans un meme panier l'entité Java, peut-etre une mauvaise habitude, mais bon...super important en effet
petit exemple concret pour les generiques en ECMAscript (pas JAVA hein, et simplifié):
_global.AtrributeType = {};le autocasting de ECMAscript cast automatiquement le boolean contenu dans Attribute en 0 ou 1 la methode valueOf permet de definir la signature de l'objet et de ne pas s'occuper du type ca permet ainsi de passer au choix une instance creer par un constructeur que directement un Number, ou juste une var contenant une value Number le ASSetPropFlags ayant besoin d'un type number en 3eme paramettre, va directement appeler la methode valueOf de l'objet qu'on lui passe, le coté générique de la "class" Attribute vient du fait que sa signature objet renvoie un type Number new Attribute( true ) est équivalent a 1 note: on aurait pu aussi forcer un cast ou meme un parseInt dans la methode valueOf, mais ce n'est pas necessaire c'est le langage qui s'occupe de faire le casting. en AS2:AttributeType.none = 0;
AttributeType.dontEnum = 1;
_global.Attribute = function( /*Boolean*/ dontEnum )
{
this.dontEnum = dontEnum;
}
Attribute.prototype.valueOf = function()
{
return this.dontEnum;
}
Attribute.setAttribute = function( target, prop, attrib )
{
ASSetPropFlags( target, prop, attrib );
}
//usage
toto = ();
toto.hello = "world";
monAttrib = new Attribute( true );
//au choix
//Attribute.setAttribute( toto, "hello", monAttrib );
//Attribute.setAttribute( toto, "hello", 1);
//Attribute.setAttribute( toto, "hello", AttributeType.dontEnum );
class Attribute {static function setAttribute( target:object, property:String, attrib:Attribute ) {
...
}
}
on ne peut pas avoir de paramettres de fonction faisant de l'autocasting, et donc qui supporte un comportement generique, car le compilo verifie le constructeur de l'objet et non pas la signature de l'objet (valueOf). (note: je n'ai pas reverifié le code que je viens de mettre c'est mis de tete, mais ces problemes de casting existent bel et bien)
Apres oui on peut me sortir, mais naaaaaaaaaan t'as qu'a crée une Interface IAttribute et comme ca dans ton param tu mets pas le type de la class mais le type de l'interface ce qui permet de passer differents types d'objet
static function setAttribute( ..., attrib:IAttribute )
mais non, je ne veux pas oublier un comportement inhérent a ECMAscript simplement parce que AS2 ne le gere pas au niveau du compilo et simplement parce que c'est pas comme ca que ca se fait en JAVA.
Fil des commentaires de ce billet