Les enums (classes limitées)
Parfois on connais déjà le domaine d'une classe et il est assez réduit. Par exemple si on a une classe Suit
, on sait déjà que les seules valeurs possibles sont Spade
, Heart
, Diamond
et Tremol
.
On peut un peu imaginer les enums comme des collections de constantes. Contrairement à d'autres languages de programmation comme le Rust où les enum
sont plus flexibles.
Définition d'une enum simple
Dans ce cas on peut donc créer un objet special appellé enum
en y définissant les valeurs possibles :
public enum Suit {
SPADE, HEART, DIAMOND, TREMOL;
// On pourrait créer nos méthodes ici si on a en a
public int getValue() {
// On peut utiliser un swicth pour tester un enum (this fait référence à l'objet actuel)
switch (this) {
case SPADE: return 1;
case HEART: return 2;
case DIAMOND: return 3;
case TREMOL: return 4;
default: return 0; // Une valeur par défault est obligatoire même si tous les cas ont été traité
}
}
// TODO Faire un exemple avec les positions des objets
public void print() {
// Les enums ont une valeur string par défault
System.out.println(this); // Va écrire SPADE, HEART, DIAMOND ou TREMOL dans la console
}
// On peut aussi récupérer un membre d'un enum depuis un String
public static Suit getSuitFromString(String name) {
// Attention ! Le nom est case sensitive et si le nom n'est pas trouvé le programme va crash
return Suit.valueOf(name);
}
}
Définition d'une enum avec attributs
Mais on peut aussi avoir des attributs dans des enums :
public enum Suit {
SPADE(false), HEART(true), DIAMOND(true), TREMOL(false);
// On va avoir un seul attribut ici appellé "isRed" pour savoir la couleur de la carte
// Il est condiéré être une bonne pratique de mettre les attributs en final car ils ne sont pas sensé être modifié
private final boolean isRed;
// On crée un constructeur pour pouvoir modifier cette valeur
// Le constructeur n'est pas public car on ne peut pas créer de nouveaux objets
Suit(boolean isRed) {
this.isRed = isRed;
}
// On va juste faire une petite méthode pour montrer que l'on récupère cet attribut comme dans une classe
public String getColor() {
if (this.isRed) {
return "Red";
} else {
return "Black";
}
}
}
Comment utiliser une enum
Maintenant pour l'utiliser on a plus besoin de new
:
// On met l'objet SPADE dans une variable "spade" de type "Suit"
Suit spade = Suit.SPADE;
// On peut récupérer la position d'un élément dans un enum avec .ordinal()
System.out.printf("La position de HEART dans l'enum est : %d\n", Suit.HEART.ordinal());
// On peut aussi retrouver un élément par sa position en transformant l'enum en Array et en prenant la position 1
Suit heart = Suit.values()[1];
// Et on peux comparer les positions de deux avec .compareTo()
int difference = heart.compareTo(Suit.HEART);
System.out.printf("Si 0 == %d alors c'est un coeur\n", difference);
// On peut maintenant comme n'importe quel classe, appeller ses méthodes tel que "getColor()"
System.out.println(spade.getColor());
Convertir une enum en une autre
Mais on peut aussi transformer une enum en une autre si les noms sont compatibles.
// Disons une permiere enum "Foo" qui as un attribut String value
// Les attributs vont être perdu lors de la conversion en revanche
enum Foo {
ONE("hello"), TWO("world"), THREE("foo"), FOUR("bar");
private final String value;
Foo(String value) {
this.value = value;
}
public String getValue() {
return this.value;
}
}
// Voici une seconde enum "Bar", la clé ici est que les membres de Foo et de Bar ont le même nom
enum Bar {
ONE, TWO, THREE, FOUR;
}
// Disons que l'on veut convertir des membres de Foo en Bar
Foo first = Foo.ONE;
// Pour cela on peut prendre le nom de foo avec toString
String name = first.toString();
// Ensuite on peut récupérer le membre du deuxième sur base de son nom avec valueOf
Bar second = Bar.valueOf(name);
// Et donc maintenant "second" vaut bien Bar.ONE et que first vaut toujours bien Foo.ONE
System.out.println(second.equals(Bar.ONE)); // affiche true
System.out.println(first.equals(Foo.ONE)); // affiche true
Résumé
Un enum en Java :
- Est un moyen de fixer le domaine d'une classe à quelques éléments
- Est immuable (on ne peut pas ajouter de nouveaux objets, ni modifier les attributs)
- Supporte l'utilisation de Switch et peuvent être automatiquement converti en String.
- Chaque membre possède une position et on peut comparer les différents objets par leurs positions.
- Ne nécésite pas de
new
pour être instancié. - Ses attributs doivent être
private final
pour le rendre immuable et encapsuler ses attributs.
Les méthodes par défault des enums :
-
.compareTo(AutreEnum)
pour comparer les positions de 2 membres d'un enum -
.ordinal()
pour avoir la position d'un membre de l'enum -
.values()
pour convertir l'enum en tableau -
.toString()
donne le nom du membre de l'enum -
.valueOf(String)
pour récupérer un enum à partir d'un String (donc avec toString très utile pour convertir 2 enums qui ont les même noms de membres)