Rechercher
 

Définition de types énumérés en Java

Utilisation de tableaux Inférence de types sur les variables locales



Accès rapide :
La vidéo
Définition d'un type énuméré simple
Association des états d'un type énuméré avec de valeurs numériques

La vidéo

Cette vidéo vous explique ce qu'est un type énuméré et comment en définir un en Java.


Définition d'un type énuméré

Définition d'un type énuméré simple

Un type énuméré est un type de données comportant en ensemble fini d'états (de valeurs). On donne à chaque état un nom, ce qui sera plus facile à utiliser plutôt qu'une valeur numérique. Un type énuméré s'introduit avec le mot clé enum. Conventionnellement, le nom du type énuméré commence par une majuscule (tout comme pour une classe). De même, les noms des états sont écrits intégralement en majuscules et on sépare chaque mot via un caractère _ (underscore). Voici un exemple de définition de type énuméré : il nous permettra de représenter les états d'un feu tricolore de signalisation routière.

 1 
 2 
 3 
 4 
 5 
public enum Feu {

    VERT, ORANGE, ROUGE
    
}
Définition d'un type énuméré

D'une certaine manière, un type énuméré ressemble au type boolean dans le sens ou l'ensemble des états connus pour le type est fini. Comme pour une classe, un type énuméré est très souvent déclaré dans son propre fichier (ici Feu.java) : si c'est bien le cas, alors le mot clé public est requis pour avoir accès à ce nouveau type de l'extérieur du fichier.

un type (classe ou type énuméré) public doit être déclaré dans un fichier de même nom (à l'extension près) en utilisant exactement les mêmes minuscules et majuscules.
Une fois le type énuméré créé, il vous est possible de l'utiliser dans votre programme pour déclarer des variables et vous pourrez affecter à ces variables les états autorisés par votre type énuméré. Voici un petit exemple d'utilisation.
 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
public class Demo {

    // Pour permettre la saisie à partir de la console
    static BufferedReader keyboard = new BufferedReader( new InputStreamReader( System.in ) );
    
    
    public static void main(String[] args) throws Exception {
        
        // La variable feu est basée sur notre type énuméré
        Feu feu = Feu.ORANGE;
        
        System.out.print( "Que voulez-vous faire (passer, attendre) : " );
        String action = keyboard.readLine();
                
        if ( action.equals( "passer" ) ) {
            // On compare les états du type énuméré
            if ( feu != Feu.VERT ) {
                System.out.println( "Vous ne pouvez pas passer, cas le feu n'est pas vert" );
            } else {
                System.out.println( "Bonne route" );
            }
        } else if ( action.equals( "attendre" ) ) {
            if ( feu == Feu.VERT ) {
                System.out.println( "Vous devez passer, les autres attendent derrière vous" );
            } else {
                System.out.println( "Bonne initiative" );
            }
        } else {
            System.out.println( "Commande inconnue" );
        }
        
    }
    
}
Utilisation du type énuméré Feu
les types énumérés existent en Java que depuis sa version 5.0. Auparavant, on se contentait de définir des constantes sur classes pour simuler la notion de types énumérés. Du coup, y compris au sein des librairies standards de Java, on aurait pu envisager à de multiples endroits d'utiliser ces types énumérés, mais il en est rien car elles ont étaient écrites avant cette version. De plus, pour des histoires de comptabilité de code avec les programmes existants, ces librairies n'ont pu être réécrites.

Il est possible d'utiliser l'instruction switch pour tester les différents états d'un type énuméré. Nous reviendrons plus précisément sur l'instruction switch dans le chapitre relatif aux instructions Java. Pour l'heure, voici un exemple qui teste l'état d'une variable de type Feu en utilisant cette instruction.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
public class Demo {

    public static void main(String[] args) throws Exception {
        
        Feu feu = Feu.ORANGE;
        
        switch ( feu ) {
            case VERT:
                System.out.println( "On peut passer" );
                break;
            case ORANGE:
                System.out.println( "Attention..." );
                break;
            default:
                System.out.println( "Faut absolument s'arréter !!!" );
        }
        
    }
    
}
Exemple d'utilisation d'un switch sur un type énuméré

Il est important de ne pas oublier les break à la fin de chaque cas, sans quoi l'exécution se poursuit au cas suivant. Le bloc default déclenche dans tous les autres cas, mais dans notre exemple, il ne reste qu'un seul cas non traité : si le feu est rouge.

Association des états d'un type énuméré avec de valeurs numériques

cette partie s'adresse aux personnes connaissant déjà les concepts de programmation orienté objet. Si ce n'est pas encore votre cas, passez pour le moment au chapitre suivant. Vous pourrez revenir sur cette section plus tard, quand les notions de constructeurs, d'attributs et de méthodes vous seront plus familières.

Si vous programmez déjà en langage C, vous avez certainement cherché à comparer les types énumérés du langage Java avec ceux du langage C. En fait, ces mécanismes sont franchement bien différents d'un langage à l'autre. En C, un type énuméré est un sous-ensemble du type int pour lequel chaque valeur numérique est associée à une constante : en C, on peut aussi bien utiliser la valeur numérique, que la constante associée. Par contre en Java, cette association valeur numérique/état n'est pas intrinsèque au langage. Si vous cherchez à l'avoir, il faudra l'implémenter de A à Z.

Je vous propose d'abord le code d'un type énuméré réalisant cette association, puis quelques explications suivront.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
public enum Feu {

    VERT(0), ORANGE(1), ROUGE(2);


    private int value;

    private Feu( int value ) {
        this.value = value;
    }

    public int toInt() {
        return value;   
    }
    
    public static Feu fromInt( int value ) {
        switch( value ) {
            case 0: return VERT;
            case 1: return ORANGE;
            default: return ROUGE;
        }
    }
    
}
Type énuméré avec association état/valeur numérique

Première chose à noter : en fait, un type énuméré est très proche d'une classe. Si vous souhaitez y ajouter des attributs ou des méthodes, il ne faut pas oublier le ; en ligne 3. Précédemment, il n'était pas utile, car seuls les états étaient spécifiés.

Chaque état sera, en réalité, une instance statique portée par le type énuméré. En fait, on aurait pu imaginer le code suivant : ce n'est plus un enum, mais une classe et les états sont définis sous formes d'attributs statiques. Vous en conviendrez certainement, la syntaxe enum n'est que du « sucre syntaxique » (afin d'adoucir la syntaxe Java).

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
public class Feu {
    
    public static final Feu VERT = new Feu(0);
    public static final Feu ORANGE = new Feu(1);
    public static final Feu ROUGE = new Feu(2);
    
    private int value;

    private Feu( int value ) {
        this.value = value;
    }

    public int toInt() {
        return value;   
    }
    
    public static Feu fromInt( int value ) {
        switch( value ) {
            case 0: return VERT;
            case 1: return ORANGE;
            default: return ROUGE;
        }
    }
    
}
Comparaison des syntaxes enum et class

Reprenons le code initial : il est donc nécessaire de maintenir la valeur numérique associée à chaque état sous forme d'attribut. Notez bien que le constructeur est défini en private : c'est important, sinon un utilisateur pourrait produire d'autres états. Mais ne vous inquiétez pas trop, car si vous ne respectez pas ce point, le message d'erreur suivant sera produit lors de la compilation de votre type énuméré.

$> javac Feu.java
Feu.java:9: error: modifier public not allowed here
    public Feu( int value ) {
           ^
1 error
$>

Ensuite deux méthodes de passage « numérique -> état » et « état -> numérique » simplifieront les transitions. Le code suivant vous montre comment utiliser notre type énuméré.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
public class Demo {

    public static void main( String [] args ) {

        Feu feu = Feu.ORANGE;
        int value = feu.toInt();
        System.out.println( "ORANGE is associate to " + value );
        System.out.println( "2 is associate to " + Feu.fromInt( 2 ) );

    }
}
Utilisation de nos associations

Pour finir, notez qu'en Java vous pouvez réaliser l'association des états avec autres choses que des valeurs numériques. Vous pouvez, par exemple, imaginer une association état/chaîne de caractères, ...



Utilisation de tableaux Inférence de types sur les variables locales