Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Comment coder un enum via une classe « normale »

59 réponses
Avatar
Francois
Bonjour à tous,

Ma question n'a pas un grand intérêt pratique, c'est juste pour
comprendre les enum. En fait, je comprends bien l'utilité des enum et la
façon dont on s'en sert. Mais, si j'ai bien compris, le mot clé "enum" a
été créé dans la version 1.5 de Java pour avoir un type énuméré en deux
coup de cuillère à pot, sachant qu'avant la version 1.5 il fallait coder
soi-même sa propre classe donnant le type énuméré souhaité.

Justement, on codait comment en version 1.4 (ou antérieure) ? Par
exemple, comment avec une classe « normale » peut-on coder un équivalent
de cet exemple très simple de type enum :

public enum Etat {
DEHORS,
DEDANS
}

Merci d'avance.

--
François Lafont

10 réponses

2 3 4 5 6
Avatar
Samuel Devulder
Yliur a écrit :

Oui, mais c'est un peu biaisé comme comparaison de lisibilité :) .
On peut aussi écrire les if / else if comme ça :

if(o.getEnum()==Enum.val1) {
// traitement 1
} else if(o.getEnum()==Enum.val2) {
// traitement 2
} else if(o.getEnum()==Enum.val3) {
// traitement 3
} else {
// comme cela sur 8 ou 9 valeurs
}



C'est vrai, mais ca dépend souvent du formatteur de l'IDE utilisé, et
j'ai eu un projet ou ce *ù$ù$* d'Eclipse mettait des {} partout, et
surtout dans le else même si ce dernier ne contenait qu'une seule
instruction (évidemment interdit de modifier le formatteur pour ne pas
changer le formattage et perturber les code-merge en gestion de conf).

Cela dit, le fait de multiplier les o.getEnum() c'est aussi multiplier
les risques de se planter si l'on a plusieurs variables u/o1/o2 du même
type (pb des copier/collés). Avec le switch, tu ne fais qu'un seul
getEnum() et c'est mois risqué (en plus d'être un peu plus rapide aussi).
Avatar
Wykaaa
Samuel Devulder a écrit :
Yliur a écrit :

Oui, mais c'est un peu biaisé comme comparaison de lisibilité :) .
On peut aussi écrire les if / else if comme ça :

if(o.getEnum()==Enum.val1) {
// traitement 1
} else if(o.getEnum()==Enum.val2) {
// traitement 2
} else if(o.getEnum()==Enum.val3) {
// traitement 3
} else {
// comme cela sur 8 ou 9 valeurs
}



C'est vrai, mais ca dépend souvent du formatteur de l'IDE utilisé, et
j'ai eu un projet ou ce *ù$ù$* d'Eclipse mettait des {} partout, et
surtout dans le else même si ce dernier ne contenait qu'une seule
instruction (évidemment interdit de modifier le formatteur pour ne pas
changer le formattage et perturber les code-merge en gestion de conf).



C'est une règle de bonne programmation élémentaire que de mettre des
paires d'accolades même s'il n'y a qu'une seule instruction dans la
famille des langages C/C++/Java. Tous les manuels de règles de
programmation dans les entreprises mentionne cette règle, je le répète,
élémentaire.

Mais la discussion ne portait pas sur les mérites (?) respectifs des
if...else imbriqués ou des switch, elle portait sur leur élimination au
profit du polymorphisme.

Cela dit, le fait de multiplier les o.getEnum() c'est aussi multiplier
les risques de se planter si l'on a plusieurs variables u/o1/o2 du même
type (pb des copier/collés). Avec le switch, tu ne fais qu'un seul
getEnum() et c'est mois risqué (en plus d'être un peu plus rapide aussi).



On peut mettre le résultat de o.getEnum() dans une variable locale et
tester cette variable dans la cascade de if/else (c'est ce que fera un
bon optimiseur, d'ailleurs).
Avatar
Samuel Devulder
Wykaaa a écrit :

On peut mettre le résultat de o.getEnum() dans une variable locale et



Oui c'est ce qu'il faudrait faire.

tester cette variable dans la cascade de if/else (c'est ce que fera un
bon optimiseur, d'ailleurs).



L'optimisateur ne peut pas faire cela car il ne sait pas si l'appel à
getEnum() ne fait pas d'effet de bords. Le seul compilo que j'ai vu
faire cela c'est GCC quand on déclare la fonction avec
__attribute__((const)):

__attribute__ const

This attribute marks the function as considering only its
numeric parameters. This is mainly intended for the compiler to
optimize away repeated calls to a function that the compiler
knows will return the same value repeatedly. It applies mostly
to math functions that have no static state or side effects, and
whose return is solely determined by the inputs.

mais on s'éloigne de la question des enums là, et le gain est quand même
souvent marginal (utiliser un profiler pour voir si on ne passe pas
plus de temps que nécéssaire dans le code d'aiguillage avec les if/else/if).

sam :)
Avatar
Yliur
Wykaaa a écrit :
Samuel Devulder a écrit :
Yliur a écrit :

Oui, mais c'est un peu biaisé comme comparaison de lisibilité :) .
On peut aussi écrire les if / else if comme ça :

if(o.getEnum()==Enum.val1) {
// traitement 1
} else if(o.getEnum()==Enum.val2) {
// traitement 2
} else if(o.getEnum()==Enum.val3) {
// traitement 3
} else {
// comme cela sur 8 ou 9 valeurs
}



C'est vrai, mais ca dépend souvent du formatteur de l'IDE utilisé, et
j'ai eu un projet ou ce *ù$ù$* d'Eclipse mettait des {} partout, et
surtout dans le else même si ce dernier ne contenait qu'une seule
instruction (évidemment interdit de modifier le formatteur pour ne pas
changer le formattage et perturber les code-merge en gestion de conf).



C'est une règle de bonne programmation élémentaire que de mettre des
paires d'accolades même s'il n'y a qu'une seule instruction dans la
famille des langages C/C++/Java. Tous les manuels de règles de
programmation dans les entreprises mentionne cette règle, je le répète,
élémentaire.



Euh... oui merci, mais là c'est un cas particulier, plus ou moins équivalent
au switch... D'ailleurs dans certains langages de programmation on peut
écrire "elsif". En Java ou en C/C++ on utilise cette forme.


Mais la discussion ne portait pas sur les mérites (?) respectifs des
if...else imbriqués ou des switch, elle portait sur leur élimination au
profit du polymorphisme.




C'est vrai :)
Avatar
Wykaaa
Samuel Devulder a écrit :
Wykaaa a écrit :

On peut mettre le résultat de o.getEnum() dans une variable locale et



Oui c'est ce qu'il faudrait faire.

tester cette variable dans la cascade de if/else (c'est ce que fera un
bon optimiseur, d'ailleurs).



L'optimisateur ne peut pas faire cela car il ne sait pas si l'appel à
getEnum() ne fait pas d'effet de bords. Le seul compilo que j'ai vu
faire cela c'est GCC quand on déclare la fonction avec
__attribute__((const)):



Ah et bien heureusement qu'il n'y a pas que GCC qui sait faire cela car
le const sur les prototype a été inventé, entre autre, pour que les
compilos puissent faire cette optimisation (j'ai fait des compilos).

[snip le reste]
Avatar
Samuel Devulder
Wykaaa a écrit :

Ah et bien heureusement qu'il n'y a pas que GCC qui sait faire cela car
le const sur les prototype a été inventé, entre autre, pour que les



Un truc dans le genre:
extern int foo() const;

compilos puissent faire cette optimisation (j'ai fait des compilos).



C'est supporté à partir de quelle norme C (pas C++, C) ? Ca m'intéresse
de pouvoir décrire cela de façon portable en C effectivement.

Mais enfin ici on s'éloigne complètement de java qui n'a pas un tel
attribut sur les méthodes.

sam.
Avatar
Wykaaa
Samuel Devulder a écrit :
Wykaaa a écrit :

Ah et bien heureusement qu'il n'y a pas que GCC qui sait faire cela
car le const sur les prototype a été inventé, entre autre, pour que les



Un truc dans le genre:
extern int foo() const;



Quand tu parlais de GCC, je pensais à C++ car GCC ne compile pas que du C !

compilos puissent faire cette optimisation (j'ai fait des compilos).



C'est supporté à partir de quelle norme C (pas C++, C) ? Ca m'intéresse
de pouvoir décrire cela de façon portable en C effectivement.



Non pas en C !

Mais enfin ici on s'éloigne complètement de java qui n'a pas un tel
attribut sur les méthodes.



C'est vrai :-)
Avatar
Samuel Devulder
Wykaaa a écrit :

Quand tu parlais de GCC, je pensais à C++ car GCC ne compile pas que du C !



g++ alors :) Mais sinon il y a g77 pour le fortran 77, gcc pour le c, et
enfin gcj pour le java qui nous ramène dans le newsgroup (ouf!).

sam.
Avatar
Francois
(Re)bonjour,

Je me permets de relancer un tout petit peu le fil (j'espère que ça ne
vous pose pas de problème) car il y encore un petit point que j'aimerais
éclaircir : c'est à propos de la "chasse aux switch" grâce au
polymorphisme. Je vais poser ma question et ensuite donner un exemple
concret.

Dans un programme où il y a des cas dichotomiques à traiter, même en
usant et abusant du polymorphisme, sommes nous d'accord *qu'au bout du
compte* on finira quand même par avoir au moins un switch (ou des séries
de "if", mais ça revient au même) quelque part dans le code, bien
localiser dans le code, certes (par exemple dans un seul endroit du
code), mais au moins un swich une fois) ?
En gros, la "chasse au switch" avec le polymorphisme d'accord, mais ça
ne permet pas une éradication *totale* dans le code, non ?


Par exemple prenons un jeu de Tetris simplifié qui contient que des
pièces carrés et des demi-T (en forme de "L"). La façon dont on les fait
tourner est différente (pour un carré il ne se passe rien au final,
alors que pour des demi-T, il se passe quelque chose).

J'imagine qu'il y aura une classe abstraite Piece qui contient une
méthode abstraite faireTourner(). Puis, on aura deux classes Carre et
DemiT qui hériteront de la classe Piece et qui implémenteront à leur
manière la méthode faireTourner(). Ok.

Mais au final, dans mon Tetris, dès fois je vais tomber sur un carré et
dès fois sur un demi-T de mamière aléatoire. Donc, au final, forcément
quelque part dans le code j'aurais au moins une fois un swith (ou des
if), non ?

Merci d'avance.



--
François Lafont
Avatar
Wykaaa
Francois a écrit :
(Re)bonjour,

Je me permets de relancer un tout petit peu le fil (j'espère que ça ne
vous pose pas de problème) car il y encore un petit point que j'aimerais
éclaircir : c'est à propos de la "chasse aux switch" grâce au
polymorphisme. Je vais poser ma question et ensuite donner un exemple
concret.

Dans un programme où il y a des cas dichotomiques à traiter, même en
usant et abusant du polymorphisme, sommes nous d'accord *qu'au bout du
compte* on finira quand même par avoir au moins un switch (ou des séries
de "if", mais ça revient au même) quelque part dans le code, bien
localiser dans le code, certes (par exemple dans un seul endroit du
code), mais au moins un swich une fois) ?
En gros, la "chasse au switch" avec le polymorphisme d'accord, mais ça
ne permet pas une éradication *totale* dans le code, non ?



On en fait la chasse, ça ne veut pas dire qu'il n'en restera aucun
vivant ;-)
C'est comme les goto, dans un langage qui ne possède pas un mécanisme
d'exception, on est bien obligé d'avoir un ou des goto pour traiter des
exceptions (par exemple, setjump/longjump en C).


Par exemple prenons un jeu de Tetris simplifié qui contient que des
pièces carrés et des demi-T (en forme de "L"). La façon dont on les fait
tourner est différente (pour un carré il ne se passe rien au final,
alors que pour des demi-T, il se passe quelque chose).

J'imagine qu'il y aura une classe abstraite Piece qui contient une
méthode abstraite faireTourner(). Puis, on aura deux classes Carre et
DemiT qui hériteront de la classe Piece et qui implémenteront à leur
manière la méthode faireTourner(). Ok.



Jusque la, rien à dire.

Mais au final, dans mon Tetris, dès fois je vais tomber sur un carré et
dès fois sur un demi-T de mamière aléatoire. Donc, au final, forcément
quelque part dans le code j'aurais au moins une fois un swith (ou des
if), non ?



Tu veux dire qu'il y aura un mécanisme de décision (if ou switch) à la
suite du tirage aléatoire pour savoir s'il faut créer telle ou telle pièce ?
La réponse est oui, car les switch qui restent sont ceux qui dépendent
de mécanismes non typés. Par exemple, dans une analyse lexicale, ce qui
est lu est le fichier d'entrée (donc des caractères). Là on est bien
obligé d'avoir des if pour savoir si on a lu un opérateur, un blanc, un
chiffre, etc... car ce qu'on lit est non typé.
2 3 4 5 6