CodeGym /Blog Java /Random-FR /Enum. Exemples pratiques. Ajout de constructeurs et de mé...
Auteur
Alex Vypirailenko
Java Developer at Toshiba Global Commerce Solutions

Enum. Exemples pratiques. Ajout de constructeurs et de méthodes

Publié dans le groupe Random-FR
Salut! Aujourd'hui, nous allons parler d'un des types de données spéciaux de Java : Enum(abréviation de "énumération"). Qu'est-ce qui le rend spécial? Imaginons ce dont nous avons besoin pour implémenter des "mois" dans un programme. Enum.  Exemples pratiques.  Ajout de constructeurs et de méthodes - 1 Cela ne semble pas problématique, non ? Nous avons juste besoin de déterminer les propriétés de chaque mois. Peut-être avons-nous d'abord besoin du nom du mois et du nombre de jours qu'il contient. La solution semble assez simple :

public class Month {

   private String name;
   private int daysCount;

   public Month(String name, int daysCount) {
       this.name = name;
       this.daysCount = daysCount;
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   public int getDaysCount() {
       return daysCount;
   }

   public void setDaysCount(int daysCount) {
       this.daysCount = daysCount;
   }

   @Override
   public String toString() {
       return "Month{" +
               "name='" + name + '\'' +
               ", daysCount=" + daysCount +
               '}';
   }
}
Tout le shabang ! Nous avons une Monthclasse, les champs obligatoires, getter/setters et toString(). À moins, bien sûr, que nous ayons besoin d'ajouter equals()ethashCode()pour atteindre le bonheur complet :) Mais ici nous avons un problème conceptuel. Comme vous vous en souvenez probablement, l'un des principaux avantages de la POO est qu'il facilite la modélisation d'entités du monde réel. Une chaise, une voiture, une planète - tous ces concepts de la vie ordinaire sont facilement représentés dans un programme à l'aide de l'abstraction. Le problème est que certaines entités du monde réel ont une plage de valeurs strictement limitée. Il n'y a que 4 saisons dans une année. Il n'y a que 8 notes dans une octave. Le calendrier ne compte que 12 mois. Et Danny Ocean de Ocean's 11 n'a que 11 amis (bien que cela n'ait pas d'importance :)) Ce qui compte, c'est qu'une classe Java ordinaire ne soit pas capable de modéliser ces entités et de faire respecter leurs limitations naturelles. NotreMonthclasse contient tous les champs obligatoires. Mais si un autre programmeur l'utilise, personne ne peut l'empêcher de créer des objets complètement fous :

public class Main {

   Month month1 = new Month("lolkek", 322);
   Month month2 = new Month("yahoooooooooooo", 12345);

}
Si cela apparaît dans notre code, il ne sera pas facile de trouver le coupable ! D'une part, le programmeur créant les objets pourrait se rendre compte que la Monthclasse signifie "mois dans une année" et ne pas écrire de telles absurdités. D'un autre côté, le programmeur ne fait que tirer parti des capacités fournies par le concepteur de classe. Est-il possible d'attribuer des noms et des nombres de jours arbitraires ? C'est exactement ce que nous avons. Que faire alors dans cette situation ? Honnêtement, avant la sortie de Java 1.5, les programmeurs devaient faire preuve de créativité :) À cette époque, ils créaient des structures comme celle-ci :

public class Month {

   private String name;
   private int daysCount;

   private Month(String name, int daysCount) {
       this.name = name;
       this.daysCount = daysCount;
   }

   public static Month JANUARY = new Month("January", 31);
   public static Month FEBRUARY = new Month("February", 28);
   public static Month MARCH = new Month("March", 31);

   @Override
   public String toString() {
       return "Month{" +
               "name='" + name + '\'' +
               ", daysCount=" + daysCount +
               '}';
   }
}
Ici, nous avons réduit le nombre de mois de douze à trois afin de raccourcir l'exemple. De telles conceptions ont permis de résoudre le problème. La possibilité de créer des objets était limitée à un constructeur privé :

private Month(String name, int daysCount) {
       this.name = name;
       this.daysCount = daysCount;
   }
Les programmeurs utilisant la classe ne pouvaient pas simplement créer Monthdes objets. Ils devaient utiliser les objets statiques finaux fournis par le développeur de la classe. Par exemple, comme ceci :

public class Main {

   public static void main(String[] args) {

       Month january = Month.JANUARY;
       System.out.println(january);
   }

}
Mais, les développeurs Java ont attiré l'attention sur le problème existant. Bien sûr, c'est bien que les programmeurs aient pu trouver une solution en utilisant les outils disponibles dans le langage, mais ça n'a pas l'air très facile ! Il fallait une solution évidente, même pour les novices. Et ainsi Enumapparu en Java. Fondamentalement, Enumest une classe Java qui fournit un ensemble limité de valeurs d'objet. Voici à quoi ça ressemble :

public enum Month {
  
   JANUARY,
   FEBRUARY,
   MARCH
}
Dans la définition, nous avons indiqué qu'il Enums'agit d'une classe Java, mais est-ce vraiment vrai ? Oui, et nous pouvons même le vérifier. Par exemple, essayez de faire hériter notre Monthénumération d'une autre classe :

public abstract class AbstractMonth {
}

// Error! The extends clause cannot be used with an enum
public enum Month extends AbstractMonth {

   JANUARY,
   FEBRUARY,
   MARCH
}
Pourquoi cela arrive-t-il ? Quand on écrit :

public enum Month
le compilateur convertit cette instruction dans le code suivant :

public Class Month extends Enum
Comme vous le savez déjà, Java ne prend pas en charge l'héritage multiple. Par conséquent, nous ne pouvons pas hériter AbstractMonth. Comment cette nouvelle construction, Enum, peut-elle être utilisée ? Et en quoi diffère-t-il de l'ancienne construction avec static finaldes champs ? Eh bien, par exemple, l'ancienne construction ne nous permettait pas d'utiliser notre propre ensemble de valeurs dans switchles instructions. Imaginons que nous souhaitions créer un programme qui nous rappellera les fêtes célébrées chaque mois :

public class HolidayReminder {

   public void printHolidays(Month month) {

       switch (month) {

           // Error!
           case JANUARY:
       }
   }
}
Comme vous pouvez le voir, le compilateur génère une erreur ici. Mais une fois enumapparu dans Java 1.5, tout est devenu beaucoup plus simple :

public enum Month {

   JANUARY,
   FEBRUARY,
   MARCH
}

public class HolidayReminder {

   public void printHolidays(Month month) {

       switch (month) {
          
           case JANUARY:
               System.out.println("New Year's Day is January 1st!");
               break;
           case FEBRUARY:
               System.out.println("Valentine's Day is February 14th!");
               break;
           case MARCH:
               System.out.println("Saint Patrick's Day is March 17th!");
               break;
       }
   }
}


public class Main {

   public static void main(String[] args) {

       HolidayReminder reminder = new HolidayReminder();
       reminder.printHolidays(Month.JANUARY);

   }

}
Sortie console :

New Year's Day is January 1st!
Notez que l'accès aux Enumobjets est resté statique, comme c'était le cas avant Java 1.5. Nous n'avons pas besoin de créer un Monthobjet pour accéder aux mois. Lorsque vous travaillez avec des énumérations, il est très important de ne pas oublier qu'il Enums'agit d'une classe à part entière. Cela signifie que, si nécessaire, vous pouvez y définir des constructeurs et des méthodes. Par exemple, dans le fragment de code précédent, nous avons simplement spécifié les valeurs : JANVIER, FÉVRIER, MARS. Cependant, nous pouvons étendre notre Monthénumération comme ceci :

public enum Month {

   JANUARY("January", 31),
   FEBRUARY("February", 28),
   MARCH("March", 31),
   APRIL("April", 30),
   MAY("May", 31),
   JUNE("June", 30),
   JULY("July", 31),
   AUGUST("August", 31),
   SEPTEMBER("September", 30),
   OCTOBER("October", 31),
   NOVEMBER("November", 30),
   DECEMBER("December", 31);

   private String name;
   private int daysCount;

   Month(String name, int daysCount) {
       this.name = name;
       this.daysCount = daysCount;
   }

   public static Month[] getWinterMonths() {

       return new Month[]{DECEMBER, JANUARY, FEBRUARY};
   }

   public static Month[] getSummerMonths() {

       return new Month[]{JUNE, JULY, AUGUST};
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   public int getDaysCount() {
       return daysCount;
   }

   public void setDaysCount(int daysCount) {
       this.daysCount = daysCount;
   }

   @Override
   public String toString() {
       return "Month{" +
               "name='" + name + '\'' +
               ", daysCount=" + daysCount +
               '}';
   }
}
Ici, nous avons donné nos enum2 champs (le nom du mois et le nombre de jours), un constructeur qui utilise ces champs, les getter/setters, la toString()méthode et 2 méthodes statiques. Comme vous pouvez le voir, il n'y a eu aucun problème avec cela. Encore une fois, Enumc'est vraiment une classe à part entière:

import java.util.Arrays;

public class Main {

   public static void main(String[] args) {

       System.out.println(Arrays.toString(Month.getSummerMonths()));

   }

}
Sortie console :

[Month{name='June', daysCount=30}, Month{name='July', daysCount=31}, Month{name='August', daysCount=31}]
Enfin, je veux recommander un livre Java extrêmement utile, à savoir "Effective Java" de Joshua Bloch . Enum.  Exemples pratiques.  Ajouter des constructeurs et des méthodes - 3L'auteur est l'un des créateurs de Java, vous pouvez donc certainement faire confiance à ses conseils pour utiliser correctement et avec compétence les outils du langage :) En ce qui concerne notre leçon, je vous recommande de porter une attention particulière au chapitre du livre sur Enum. Bonne lecture! :)
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION