Switch/case original : tester la classe d'une variable
Par -Alexandre LEGOUT aka LAlex- le 15 février 2006, 14:19 - AS2 - Lien permanent
Pour ceux qui ne lisent pas la mailing-list de OSFlash, Ralf Bokelberg y donne une petite astuce pour tester la classe d'une variable, et de manière plus globale comment éviter une succession de if...else if...else.
En fait, le switch...case a pour limitation de ne servir qu'à comparer une valeur à une autre (ou plusieurs autres), alors qu'un if va vérifier si une condition est vraie. Mais, et c'est là qu'est l'astuce, vérifier si une condition est vraie consiste uniquement à comparer son résultat à true... et voila!
Petit exemple:public static function getEnvironement(eng : Engine) : String {
var env:String = "Twilight zone";
switch(true) {
case (eng instanceof Boat):
env = "Water";
break;
case (eng instanceof Car):
case (eng instanceof Motorcycle):
case (eng instanceof Bus):
env = "Road";
break;
case (eng instanceof Plane):
env = "Sky";
break;
case (eng instanceof Spacecraft):
env = "Outerspace";
break;
default:
trace("ET???");
}
return env;
}
C'est peut-être connu, et certainement utilisable dans de nombreux langages, mais moi j'ai découvert aujourd'hui, et je trouve l'astuce bien élégante! ^^
Commentaires
Effecvivement, c'est une utilisation du switch que l'on trouve dans le moock. C'est un bon exemple d'application
Question bête : ne vaut il pas mieux rajouter un break après l'initialisation de la variable (suite à la détection de type), ceci afin d'éviter d'éxécuter de manière séquentielle tous les tests case ? Histoire de gagner (un petit petit) en temps d'éxécution...
Oups!
Autant pour moi, j'avais mis au début des return, et donc le break était inutile... :p
ouais j'ai trouver cette astuce ya pas longtemps.
ce genre de petite astuce simplifie la vie !
Génial... je vais réexploiter ça en PHP !
Hello

Dans ton exemple au dessus, la variable env dans le switch ne te renvois pas d'erreur à la compilation ?
Pour ma par j'ai un joli :
EKA+
@eka> Si en effet, voila ce que c'est de faire un exemple trop vite fait sans le compiler...
En même temps, le but était surtout d'illustrer le principe...
Corrigé
++ ^^
Oui c'est clair que le principe est peu commun (je n'avais pas pensé à faire cela ;)) et pour un pattern Strategy en AS2 cela semble une bonne chose, faudrait voir ce que cela donne avec au passage une petite reflexion sur les classes directement et en testant tout simplement le namespace de la fonction constructeur de l'instance

EKA+
Je trouve ça limite tordu mais magnifique
Enorme ! Je ne connaissai pas merci
Je trouve ça un peu bizarre comme technique, mais j'avoue que ça peut-être pratique lorsque l'on travail avec une base de code qui provient de l'extérieur. Il aurait été mieu à la base de rajouter une méthode getEnvironement() à l'interface Engine

À noter que cette technique ne s'applique pas aux languages qui n'acceptent que des nombres entier comme valeur dans un switch()
Salut Alex,
je suis pas super d'accord avec cette solution.
En prog object tu n'as pas a tester le type d'object auquel tu as affaire.
L'utilisation de instanceof est vraiment res deconseillee a part ds certains cas.
La vraie solution elegante et orientee object est de creer pour chaque calsse d'objet : Car, Bus etc.. une methode getEnv par exmple qui est appellee sur eng.
Ta methode getEnvironement se resume a
return eng->getEnv();
a+
Hello


Fred pourquoi tu déconseille l'utilisation de instanceof ?
EKA+
Il ne fait répêter ce que tous les profs de POO disent
L'utilisation du instanceof est pratique dans certain cas, mais ce n'est pas très souple et on peu très bien s'en passer avec un bon design OO. Si un comportement change en fonction d'un type et que l'on a beaucoup de types et de comportements, il est préférable d'encapsuler le comportement dans le type.
(cf. rajouter une méthode getEnvironement() à l'interface Engine)
@++
Ehoh les copains!!! :o Ce que je démontre là, c'est juste l'utilisation d'un switch...case pour autre chose qu'une comparaison de valeurs...
Si on ne veut pas utiliser de instanceof, on peut aussi se la jouer sur le cast:
switch(true) {case (!!Boat(eng)):
// blablabla...
case (!!Car(eng) || !!Motorcycle(eng)):
// blablabla...
}
Il doit bien exister a peu prés 10.000 manière de retourner cet environnement, plus ou moins recommandables, plus ou moins "clean", mais c'est une astuce que je donne, pas une leçon de POO...
Evidemment qu'il faut créer une méthode getEnvironment... :\
Mon dernier message n'était qu'une réponse à la question d'eka... Je vais m'abstenir à l'avenir.
Ca, ce serait dommage.... :'(
C'est juste que la rethorique, ca va un moment, restons dans le sujet! ^^
Il y a plusierus raisons pour lesquelles l'usage de instanceof est deconseillee et plus particulierement dans un case:
ta fonction getEnvironement doit connaitre de maniere exhaustive tous les types de tous les objets. Au niveau maintenance c'est pas super. Si tu rajoutes un type tu vas etre oblige de repercuter cette creation dans des fonctions qui n'ont rien a voir avec ton design. Je te raconte pas la prise de tete.
au niveau encapsulation c'est pas super non plus. Si durant ton developement tu veux specialiser par exemple bus et velo pour un env qui pourrait s'appeller road_plane tu dois encore modifier ta fonction, pas bien non plus. Un objet est le seul a savoir a son etat.
Les seuls cas que je connais d'utilisation de instanceof sont pour tester des sur-type d'un objet qui aurait un pere abstrait (interface). Comme par exemple pour tester l'existence d'une fonction.
if (instanceof vehicule) engine->getPetrol()
else if (instanceof velo) engine->getShoes()
Cette astuce n'est pas valable en .NET, car ce qui suit le case doit être une constante.
Mais je retiens cette astuce pour d'autres langages.
Fil des commentaires de ce billet