Des coquilles dans l'AS3
Par -Alexandre LEGOUT aka LAlex- le 27 juillet 2007, 18:44 - AS3 / Flex2 - Lien permanent
Aprés maintenant quelques un grand nombre de lignes de code en AS3, j'ai noté quelques comportements bizarres...
- la propriété "constructor" de la classe Object ne semble pas être déclarée comme publique. Donc, on se retrouve avec une contradiction entre la doc et la réalité... et surtout aucun moyen de connaitre la classe qui a servie à créer l'objet. Un workaround existe utilisant describeType:
public class ClassUtils
{
public static function getConstructor(o : *) : Class {
var clname:String = describeType(o).@name.toXMLString();
var claz:Class = getDefinitionByName(clname) as Class;
return claz;
}
}
- imaginons que je crée une interface vide (ainsi que son implémentation) qui me sert uniquement à indiquer l'appartenance à deux types simultanément: en gros, une interface qui hérite de deux interfaces. Si ces deux interfaces mères ont une méthode commune et que j'utilise mon interface fille pour typer une variable, le compilateur va me remonter une erreur comme quoi la référence à cette méthode est ambigue. Ceci est tout à fait inconcevable, car il est clair que l'implémentation utilisée sera évidemment unique! Bon, étant donné que ce charabia doit être super flou, voici un exemple:
// Voir plus bas pour les différentes interfaces
package {
import flash.display.Sprite;
import itf.IDataSet;
import itf.IList;
import cl.DataSet;
public class ASPlayground extends Sprite
{
public function ASPlayground()
{
var ids:IDataSet = new DataSet;
trace(ids.getLength()); // Erreur du compilateur: Référence ambiguë à getLength.
trace((ids as IList).getLength()); // Marche bien !
}
}
}
package itf
{
public interface IList
{
function getLength() : int;
}
}
package itf
{
public interface ICollection
{
function getLength() : int;
}
}
// Cette interface sert au typage
package itf
{
public interface IDataSet extends IList, ICollection
{
}
}
// Implémentation de IDataSet
package cl
{
import itf.IDataSet;
public class DataSet implements IDataSet
{
public function getLength():int
{
return -1;
}
}
}
Rien de bien gênant, mais ca peut parfois être troublant! ![]()
- Le workaround du premier problême fait surtout chuter les performances
- Le deuxième problême par contre ne sacrifie en rien les performances, mais peut-être gênant si on ne connait pas les interfaces mères...
Commentaires
oui, c'est curieux cette erreur de compilation
Hello
1 - pour le constructor c'est clair que c'est très étrange qu'il soit privé ? Par contre on peut toujours accéder à la variable en tapant :
[as]
var o:Object = new Object() ;
trace(o["constructor"] ;
[/as]
Je préfère largement cette syntaxe même si elle est dynamique que l'utilisation du getDefinitionByName()
2 - Pour ton exemple d'interface etc.. un truc va pas dans ton exemple non ? Tu as des interfaces qui définissent une méthode getLength() et dans ton exemple tu utilises une propriété "length"
(mais cela doit être une coquille
à mon avis 
3 - Sinon pour ma part je trouve logique qu'il y est un conflit en mettant en place 2 interfaces avec la même méthode et ensuite en utilisant un multihéritage de ces interface dans une autre.. La solution reste de créer une interface de plus bas niveau qui contiendra la définition de la méthode à isoler .. exemple :
[as]
package sample
{
public interface ISize
{
function size():int ;
}
}
package sample
{
public interface IList extends ISize
{
}
}
package sample
{
public interface ICollection extends ISize
{
}
}
package sample
{
public interface IData extends ICollection, IList
{
}
}
package sample
{
public class Data implements IData
{
public function size():int
{
return -1;
}
}
}
[/as]
Et dans la classe main quand je tape :
[as]
var data:IData = new Data() ;
trace( data.size() ) ;
[/as]
Tout marche sans problème et à mon avis c'est bien plus propre de créer des interfaces propres en faisant un petit refactoring pour éviter les duplications de méthodes dans les interfaces.
PS : il n'est plus possible de mettre du code avec la colorisation syntaxique dans les commentaires de ton blog ?
J'ai essayé toutes les
balises bbcode que je connais mais aucune ne passe ^_^ Donc désolé si le code
passe mal 
EKA+
Salut, LAlex
c'est bien une erreur de copier/coller dans ton exemple concernant la méthode getLength et ton appel à la propriété length parce que tu n'as pas définit de propriété virtuelle mais une méthode ...
J'ai envoyé un message hier ? Et on dirait qu'il est passé comme un spam non ? Si il faut je le réécrirai mais il était un peu long lol alors si il n'est pas perdu ce serait cool
EKA+
En effet, faute de frappe dans mon code, il s'agit bien d'un appel à la méthode getLength()... (rectifié)
De toutes façons, quelle que soit l'implémentation utilisée, elle sera forcément unique! L'ambiguité n'est absolument pas possible dans ce cas, et le cast totalement inutile quoi qu'il arrive...
@eka> Ton code n'est pas plus propre pour un sou: mes interfaces IList et ICollection peuvent avoir leur utilité indépendamment l'une de l'autre et justifient parfaitement le fait d'avoir une méthode getLenth() chacune.
Si on part sur le principe que tu donnes en exemple, autant prévoir une interface par méthode, et chaque interface qui aura besoin de plusieurs méthodes devra se contenter d'étendre une interface pour chacune d'elle? :o
Quant à l'utilisation des crochets pour constructor, c'est tout simplement plus efficace et moins propre...;)
++ ^^
Yes, enfin des vrai infos sur l'AS3
Fil des commentaires de ce billet