Énumérations : Java vs C

Malgré ce titre aguicheur, l’objectif n’est pas de faire un combat entre le C et le Java ^^ Je viens simplement de me pencher un peu plus en détails sur les énumérations en Java et il s’avère qu’elles sont bien plus puissantes. En même temps, elles sont basiques en C… Java tire sa force dans le fait que ses énumérations sont très proches des classes* : une énumération a un constructeur, peut avoir des champs et des méthodes.

Si je me suis intéressé aux énumérations, c’est parce que j’étais cette semaine chez un client et qu’il souhaitait accéder à des données dans un tableau grâce aux valeurs de l’énumération, comme il avait l’habitude de le faire en C. Il est vrai que lorsqu’on définit une énumération en C, on peut écrire du code comme ceci :

#include <stdio.h>

typedef enum
{
    MORNING,
    AFTERNOON,
    NIGHT
} moment_t;

const char* moment_strings[] = {"I Hate Morning...", "I can deal with Afternoon.", "Night is great !"};

const char * to_string(moment_t m)
{
    return moment_strings[m];
}

int main()
{
    printf("%s\n", to_string(MORNING));
    printf("%s\n", to_string(AFTERNOON));
    printf("%s\n", to_string(NIGHT));

    moment_t m = 42;
    printf("%s\n", to_string(m));
}

On obtient la sortie suivante dans la console :

I Hate Morning...
I can deal with Afternoon.
Night is great !
(null)

Les valeurs énumérées sont des entiers en C et le compilateur ne râle pas quand on affecte 42 dans une variable de type moment_t. Il faut donc rajouter des tests dans la fonction to_string() pour s’assurer qu’on est dans la plage de moment_t. La rigueur des valeurs utilisées est à la charge du développeur, comme presque toujours en C, mais on peut arriver à des constructions assez puissantes avec des énumérations.

A première vue en Java, difficile de faire la même chose avec une énumération :

package com.gradot.enums;

public enum BasicMoment {
	MORNING, AFTERNOON, NIGHT
}

Il existe une technique presque cachée : BasicMoment.MORNING.ordinal() renverra 0. On peut donc récupérer un entier pour accéder au contenu d’un tableau. Il y a bien mieux à faire en Java, en tirant partie de cette ressemblance très forte avec une classe*. On peut par exemple faire ceci :

package com.gradot.enums;

public enum Moment {
		MORNING("I Hate Morning..."),
		AFTERNOON("I can deal with Afternoon."),
		NIGHT("Night is great !");
		
		private final String message;

		private Moment(String message) {
			this.message = message;
		}
		
		public String getMessage() {
			return message;
		}
	
	public static void main(String[] args) {
		System.out.println(Moment.MORNING.getMessage());
		System.out.println(Moment.AFTERNOON.getMessage());
		System.out.println(Moment.NIGHT.getMessage());
	}
}

Lorsqu’on définit les valeurs de l’énumération, on fait appel au constructeur (qui est forcément privé, car on ne peut pas rajouter de valeur à l’énumération). On peut ainsi conserver le message directement dans un champ. On peut enfin définir un getter pour récupérer ce texte. Et bien sûr ici, il n’est pas possible d’utiliser 42 comme valeur pour une variable de type Moment.

* : en fait, les énumérations sont des classes 😉 Pour être exact, Oracle dit dans ce lien :

The enum declaration defines a class (called an enum type).

Il existe une classe abstraite appelée Enum. Et voici la hiérarchie de classes pour Enum dans mon workspace :
H
Magique, non ?

PS : woh ! C’est mon 80e article !

Publicités

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s