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
Francois
Wykaaa a écrit :

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é.



Ok. J'avais un petit doute et je me demandais si le polymorphisme ne
pouvais pas éradiquer *tous* les switch. Mais effectivement, tout ce qui
ne relève pas du type n'est pas du ressort du polymorphisme.

Merci beaucoup.


--
François Lafont
Avatar
Samuel Devulder
Francois a écrit :

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émentx
quelque part dans le code j'aurais au moins une fois un swith (ou des
if), non ?



En fait oui, pour la simple et bonne raison qu'un processeur standard
n'a fondamentalement pas de notion de d'heritage et de polymorphisme, et
que la seule chose qu'il sache faire ce sont du calcul arithméthique, et
des gotos +/- conditionnels.

Donc quoi qu'on fasse, au final le processeur il s'en tape du
polymorphisme qui est un truc qui n'a de sens que dans les couches soft
bien au dessus de lui (même l'OS s'en fiche de ce truc là).

sam.
Avatar
Samuel Devulder
Wykaaa a écrit :

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é.



Je ne suis pas 100% d'accord. Pourquoi on aurait pas une classe pour les
opérateurs, une classe pour les blancs, une classe pour les chiffres, le
tout héritant d'une classe décrivant les caractères ? Rien ne l'interdit
en théorie.

Tiens, je reprends le cas du smalltalk que je connais et qui pousse
l'objet assez loin. Dans ce langage là il n'y a pas vraiment de
booleens. Il y a une class, disons Logic, avec deux sous classe True et
False ne contenant qu'une seule instance chacune.

C'est assez mmusant, car comme il y a de la Block-Closure, les if/then
les operations booleenes s'ecrivent uniquement via le polymorphisme. On
a plus aucun if ou switch dans un code. On peut s'en approcher en java
(pas 100% identique à cause du typage fort, mais ici seul le principe
compte pour la demonstration) en remplacant les Block-Closure par des
Runnable(). Ca donnerait ceci:

// un objet qui connait les Logic
interface MyObject {
Logic eq(MyObject other);
}

// block de code
interface Runnable {
void run();
}

interface Logic extends MyObject {
Logic and(Logic other);
Logic or(Logic other);
Logic not();
Logic ifTrue(Runable code);
Logic ifFalse(Runable code);
}

public True implements Logic {
public final True TRUE = new True();
private True(){};
public Logic or(Logic other) {return this;}
public Logic and(Logic other) {return other;}
public Logic not() {return False.FALSE;}
public void ifTrue(Runnable code) {code.run(); return this;}
public void ifFalse(Runnable code) {return this;}

public Logic eq(Logic other) {return other;}
}

public False implements Logic {
public final True FALSE = new False();
private False() {};
public Logic or(Logic other) {return other;}
public Logic and(Logic other) {return this;}
public Logic not() {return False.TRUE;}
public void ifTrue(Runnable code) {return this;}
public void ifFalse(Runnable code) {code.run(); return this;}

public Logic eq(Logic other) {return other.not();}
}


Avec ceci, if(a==b) {...code1...} else {...code2...} devient:
a.eq(b)
.ifTrue(new Runnable() {public void run(){...code1...}})
.ifFalse(new Runnable() {public void run(){...code2...}});

Pas un seul if(), tout se fait par le dispatching !!

sam.
Avatar
Samuel Devulder
Samuel Devulder a écrit :

public False implements Logic {
public final True FALSE = new False();


OOps Lire:
public final False FALSE = new False();
(j'aurais mieux fait d'appeller ces trucs là INSTANCE: True.INSTANCE et
False.INSTANCE).


sam.
Avatar
Francois
Samuel Devulder a écrit :

En fait oui, pour la simple et bonne raison qu'un processeur standard
n'a fondamentalement pas de notion de d'heritage et de polymorphisme, et
que la seule chose qu'il sache faire ce sont du calcul arithméthique, et
des gotos +/- conditionnels.

Donc quoi qu'on fasse, au final le processeur il s'en tape du
polymorphisme qui est un truc qui n'a de sens que dans les couches soft
bien au dessus de lui (même l'OS s'en fiche de ce truc là).



Ok, c'est très clair.

Merci à vous deux, Samuel et Wykaaa, pour vos explications très
enrichissantes.

À+


--
François Lafont
Avatar
Alain Ketterlin
Samuel Devulder writes:

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émentx quelque part dans le code j'aurais au moins une fois un
swith (ou des if), non ?



En fait oui,



Non.

pour la simple et bonne raison qu'un processeur standard
n'a fondamentalement pas de notion de d'heritage et de polymorphisme,
et que la seule chose qu'il sache faire ce sont du calcul
arithméthique, et des gotos +/- conditionnels.



Et des branchements indirects. L'équivalent d'appeler une fonction en
C via un pointeur, d'une certaine façon. C'est comme cela que la
liaison dynamique est faite.

-- Alain.
Avatar
Wykaaa
Samuel Devulder a écrit :
Wykaaa a écrit :

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é.



Je ne suis pas 100% d'accord. Pourquoi on aurait pas une classe pour les
opérateurs, une classe pour les blancs, une classe pour les chiffres, le
tout héritant d'une classe décrivant les caractères ? Rien ne l'interdit
en théorie.



Oui, en théorie...
Je suis d'accord qu'on peut pousser le bouchon le plus loin possible
mais ça devient compliqué dans des langages qui ne sont pas 100% objet
tels que C++ ou Java.

Tiens, je reprends le cas du smalltalk que je connais et qui pousse
l'objet assez loin. Dans ce langage là il n'y a pas vraiment de
booleens. Il y a une class, disons Logic, avec deux sous classe True et
False ne contenant qu'une seule instance chacune.



Oui mais Smalltalk est un langage clos par rapport à l'objet (tout est
objet, y compris les classes, c'est pour cela qu'on y parle de
métaclasse). Alors là, c'est effectivement plus facile qu'en C++ et en
Java d'éliminer toutes les alternatives et les switch.

C'est assez mmusant, car comme il y a de la Block-Closure, les if/then
les operations booleenes s'ecrivent uniquement via le polymorphisme. On
a plus aucun if ou switch dans un code. On peut s'en approcher en java
(pas 100% identique à cause du typage fort, mais ici seul le principe
compte pour la demonstration) en remplacant les Block-Closure par des
Runnable(). Ca donnerait ceci:

// un objet qui connait les Logic
interface MyObject {
Logic eq(MyObject other);
}

// block de code
interface Runnable {
void run();
}



Je suis d'accord, il faut que chaque objet soit actif (contienne son
propre "thread" ou processus. Mais avoue que ça complique quand même les
choses. Cependant j'adore cette façon de programmer en Java mais elle
n'est pas habituelle. Ca doit être pour cette raison que dans d'autres
fils assez anciens (plusieurs années), je me suis pris des baffes ;-)

interface Logic extends MyObject {
Logic and(Logic other);
Logic or(Logic other);
Logic not();
Logic ifTrue(Runable code);
Logic ifFalse(Runable code);
}

public True implements Logic {
public final True TRUE = new True();
private True(){};
public Logic or(Logic other) {return this;}
public Logic and(Logic other) {return other;}
public Logic not() {return False.FALSE;}
public void ifTrue(Runnable code) {code.run(); return this;}
public void ifFalse(Runnable code) {return this;}

public Logic eq(Logic other) {return other;}
}

public False implements Logic {
public final True FALSE = new False();
private False() {};
public Logic or(Logic other) {return other;}
public Logic and(Logic other) {return this;}
public Logic not() {return False.TRUE;}
public void ifTrue(Runnable code) {return this;}
public void ifFalse(Runnable code) {code.run(); return this;}

public Logic eq(Logic other) {return other.not();}
}


Avec ceci, if(a==b) {...code1...} else {...code2...} devient:
a.eq(b)
.ifTrue(new Runnable() {public void run(){...code1...}})
.ifFalse(new Runnable() {public void run(){...code2...}});

Pas un seul if(), tout se fait par le dispatching !!

sam.



J'a... doooooore !
Mais je ne voulais pas effrayer François ;-)
Avatar
Wykaaa
Samuel Devulder a écrit :
Samuel Devulder a écrit :

public False implements Logic {
public final True FALSE = new False();


OOps Lire:
public final False FALSE = new False();
(j'aurais mieux fait d'appeller ces trucs là INSTANCE: True.INSTANCE et
False.INSTANCE).


sam.



On avait rectifié de nous-mêmes...
Avatar
Francois
Alain Ketterlin a écrit :

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émentx quelque part dans le code j'aurais au moins une fois un
swith (ou des if), non ?


En fait oui,



Non.



Ah, serait-ce possible d'avoir un bout de code java (même un peu
elliptique par endroit), où l'on crée dès fois une pièce de type Carre,
dès fois de type demi-T, sans utiliser le moindre switch ou if
équivalent ? Car là, je ne vois pas du tout comment c'est possible.


--
François Lafont
Avatar
Francois
Wykaaa a écrit :.

J'a... doooooore !
Mais je ne voulais pas effrayer François ;-)



C'est gentil d'avoir pensé à moi. :-)

Je garde ce code dans un coin pour essayer de le potasser, car là comme
ça c'est trop dur.


--
François Lafont
2 3 4 5 6