#AstuceDeCode 1 : les enums

On a tendance à dire que les enums de Java sont équivalents à ceux en C. Erreur ! En fait ils sont bien plus puissants, et nous allons le voir à travers un exemple.

Les enums Java héritent en fait tous de la classe java.lang.Enum. Ce sont donc bien des objets, en fait les deux choses qui changent par rapport à des objets standard Java sont le mode d’instanciation et le fait que la JVM appliquera des optimisations spécifiques aux enums.

Maintenant considérons qu’on a un Enum avec trois valeurs, A, B, C. Par ailleurs on a un objet MyObject dont l’interface contient les méthodes suivantes :

   public String getForA();
   public String getForB();
   public String getForC();

La méthode classique de coder serait la suivante :

   String value = null;

   switch (myEnum) {
      A: value = myObject.getForA();
         break;
      B: value = myObject.getForB();
         break;
      C: value = myObject.getForC();
         break;
   }

Ce code présente en fait les problèmes suivants :

Il risque d’être copié/collé dans de nombreux endroits de l’application.
– Mais surtout si on ajoute une nouvelle valeur à l’enum il faudra penser à aller modifier tous les switch/case y faisant référence pour rajouter la nouvelle valeur, bref galère…
Et pourtant il existe bien plus élégant. Rappelez-vous : les enums sont des objets en Java. La solution est d’utiliser cette propriété, voici comment :

   public enum myEnum {
      A {
         @Override
         public String getValue(MyObject obj) {
            return obj.getForA();
         }
      },
      B {
         @Override
         public String getValue(MyObject obj) {
            return obj.getForB();
         }
      },
      C {
         @Override
         public String getValue(MyObject obj) {
            return obj.getForA();
         }
      };

      public abstract String getValue(MyObject obj);
   }

Dès lors en utilisant ce nouvel enum on peut réécrire le switch/case de tout à l’heure de la manière suivante :

   String value = myEnum.getValue(myObject);

Le code ci-dessus résout les problèmes énumérés, à savoir :

– Aucun risque de dupliquer le code du switch/case, étant donné que c’est maintenant la responsabilité de l’enum de savoir comment l’instance de MyObject va être invoquée suivant la valeur de l’enum.
– Si on ajoute une valeur de l’enum on pensera immédiatement à implémenter la méthode correspondante à cette valeur, sinon le code ne compilera pas.
De la même manière les enums peuvent être porteurs de valeurs si besoin.

Cet article vous a plu ? Vous aimerez sûrement aussi :

Julien
Moi c’est Julien, ingénieur en informatique avec quelques années d’expérience. Je suis tombé dans la marmite étant petit, mon père avait acheté un Apple – avant même ma naissance (oui ça date !). Et maintenant je me passionne essentiellement pour tout ce qui est du monde Java et du système, les OS open source en particulier.

Au quotidien, je suis devops, bref je fais du dév, je discute avec les opérationnels, et je fais du conseil auprès des clients.

Son Twitter Son LinkedIn

gojul

View Comments

  • Je suis pas très fan de cette astuce de code (ou du moins de l'exemple) :x

    En réalité, l'argument du code copié/collé me semble douteux, pour l'éviter il suffit de factoriser le bout de code avec le switch à un seul endroit. La solution c'est la factorisation, pas l'enum en soit.

    Par ailleurs, on a bien souvent tendance, voire on est obligé, d'utiliser les énums dans le code en y faisant référence explicitement.

    Et c'est là où mettre de l'implémentation de code métier dedans me pose problème, notamment si on souhaite avoir une implémentation d'environnement de test différente ou pour faire de l'injection de dépendance. Dans ces cas là, ça devient la merdouille parce qu'on fait référence à l'enum directement partout dans le code, et qu'il contient une implémentation qu'on souhaite variable.

    Dans la très grande majorité des cas, je préfère utiliser les énums que pour une liste de truc (status, phases, ...), notamment en remplacement à des ids incompréhensible, tout en évitant d'y mettre à l'intérieur du code. Le code (si nécessaire) sera plutôt externalisé dans une classe métier dédiée (par exemple une factory ou un provider dans le cas cité en exemple).

    Just my 2 cents ;)

  • Bonjour,

    Alors pour vous répondre on peut tout à fait passer des enums en paramètre des méthodes, et là l'astuce évoquée prend tout son sens. Et pour être honnête ça m'est arrivé plus d'une fois.

    Ou alors avec un truc comme ça :
    Enum value = Enum.valueOf(xxx);
    value.

    Et là c'est bien plus intéressant d'utiliser le polymorphisme au niveau de l'enum que dans un switch/case.

    Le problème de la factorisation du switch case comme évoqué est en terme de maintenance, car vous risquez à un moment ou l'autre d'oublier ce bout de code le jour où vous rajoutez une valeur à l'enum. Et ce sera bien pire le jour où vous aurez plusieurs codes à modifier suivant la méthode.

    Enfin l'intérêt d'utiliser le polymorphisme pour l'enum est qu'on peut tout à fait le mocker par la suite s'il est passé en paramètre de méthode.

    Après comme toute astuce de code elle s'applique à certains cas mais pas à tous, un peu comme les design patterns quoi. ;-)

  • Pour ne pas oublier de compléter un bout de code quand on met une nouvelle valeur à l'enum, il suffit de mettre un test unitaire basique qui compte le nombre d'élément dans l'enum et le nombre de valeur différente retourné par une fonction (ou autre mais l'idée c'est le test u).

    Perso, plutôt qu'un switch (surtout pour retourner un string), je mets tout dans un dictionnaire. C'est performant et pour le test unitaire, il suffit de compter combien d'entrée a mon dictionnaire. Un oubli et le test passe rouge.

Recent Posts

Le DevSecOps, une évolution nécessaire ?

Ça n’étonnera personne si nous affirmons que le monde du développement logiciel est en constante…

6 jours ago

Travailler en tandem augmente la résilience des systèmes et le bien-être des collaborateurs !

En Allemagne, le travail en tandem à temps partiel, aussi appelé « jobsharing » est…

1 mois ago

Classement QCM saison automne : infos & règlement.

On se retrouve comme d'habitude pour le début du classement qcm saison automne ! Mais…

2 mois ago

Classement QCM saison Eté 2024 : Règlement, informations.

La saison printemps des tests techniques WeLoveDevs s'est terminée le 31 mai, et c'est Axel…

5 mois ago

Développeur autodidacte : comment me former ?

Se former en tant que développeur autodidacte peut sembler intimidant, mais c'est tout à fait…

5 mois ago

Tout savoir sur la question d’agrément CIR/CII pour les freelances en informatique

Dans le cadre de leurs développements, les entreprises se tournent de plus en plus vers…

7 mois ago