La classi Enumerate – Lezione 21 di Java Avanzato

Cosa sono le classi Enum in Java?

Le classi Enum definiscono un tipo di dati che può assumere un insieme limitato e fissato di valori. Ad esempio, un tipo di dati che rappresenta un giorno della settimana può assumere solo uno di 7 possibili valori ognuno con un determinato giorno. Supponiamo di voler implementare una classe Carta che rappresenta una carta da gioco francese. Ogni carta è caratterizzata da un valore (da 1 a 13) ed uno dei quattro semi (semi). Alla carta daremo il tipo intero, ma al seme delle carte che valore possiamo utilizzare?

  public class Carta {
    private int val;
    private ? semi;
    // ...
  }

Non c’è nessuna corrispondenza esatta con nessun tipo conosciuto, un intero ha molti più valore di quelli a noi necessari ed inoltre gli interi hanno un ordine tra i diversi valori, i semi delle carte no. Lo stesso discorso vale per una stringa, anche se dessimo un nome di tipo stringa ai semi esistono differenti modi per chiamarli (es. cuori, picche ecc.) non esiste una corrispondenza esatta tra nome e valori (le stringhe possono essere scritte in molti modi, ad esempio Cuori, cuori, CUORI, Spade, ecc.).

Come sono implementate le classi Enumerate

Fino a Java 1.4 bisognava creare una classe Semi in cui si cerca di rappresentare tutti e soli i semi delle carte. In particolare, si creavano delle costanti di classe e le si istanziava con i valori dei semi. Per evitare la creazione di ulteriori oggetti, i costruttori venivano dichiarati privati e nella loro unica invocazione creavano un’unica istanza della classa richiesta.
A partire da Java 5, tutto questo meccanico è stato reso automatico con l’introduzione delle classi enumerate con una rappresentazione molto più compatta:

  public enum Semi{
    CUORI, SPADE, QUADRI, FIORI
  }

La rappresentazione della classe Enum è equivalente alla versione con le costanti di classe, ma molto più compatta ed immediata. Una classe enumerata obbliga a scrivere nel primo rigo della classe tutti i valori, ma non solo… una classe enumerata estende Enum ed è final. I valori di una classe enumerata si utilizzano come delle vere e proprie costanti pubbliche di classe, per cui la seguente istruzione non provoca errori di compilazione:

  Semi s = Semi.CUORI;

Ad ogni costante della classe viene assegnato un assegnato in automatico un valore numerico in base all’ordine in cui sono stati scritti (nel nostro caso, a CUORI sarà assegnato zero, a SPADE uno, a QUADRI due ed infine a FIORI il valore tre). Questo valore indica la posizione occupata all’interno della classe.

Il metodo ordinal, ereditato da Enum, consente di passare da un valore enumerato al suo indice di posizione:

  public int ordinal()

Per conoscere l’indice di posizione del seme Cuori, dovremo eseguire:

  int x = CUORI.ordinal(); // In x verrà inserito 0

Per l’operazione inversa, si usa il metodo statico values che restituisce un array con gli oggetti corrispondenti:

  public static Semi[] values()

Inoltre, Enum contiene il metodo name che restituisce il nome utilizzato come definito nel codice sorgente, facendoli diventare valori reali a runtime.

  public String name()

Il metodo corrispondente che consente di passare da un nome al suo valore è valueOf.

  public static Enum valueOf(Class e, String name)

La classe e corrisponde alla classe enumerata, mentre la stringa rappresenta il nome corrisponde.

In una classe Enum è possibile aggiungere ulteriori attributi, specializzando il comportamento di un valore enumerato rispetto agli altri valori della stessa enumerazione. Ad esempio, vogliamo dotare i Cuori e i Quadri del colore rosso, per cui avremo:

  public enum Semi {
    CUORI(true), SPADE(false), QUADRI(true), FIORI(false);
    private boolean red;

    private Semi(boolean red) {
      this.red = red;
    }
  }

E costruiremo un metodo opportuno per leggere il colore del seme:

  public boolean isRed() {
    return red;
  }

Un metodo alternativo prevede l’ovverriding specifico per valori:

  public enum Semi {
    CUORI, SPADE {
      public boolean isRed() {
        return false;
      }

    },
    QUADRI, FIORI {
      public boolean isRed() {
        return false;
      }
    };

    public boolean isRed() {
      return true;
    }
  }

In questo modo si è specializzato il comportamento di un valore, inserendo il codice relativo subito dopo la dichiarazione di quel valore. Questo costrutto deve essere considerato equivalente alla creazione di una classe anonima che estende l’enumerazione stessa, il codice specifico di un valore si comporta come se fosse inserito in una apposita classe anonima. Per questo motivi è possibile inserire liberamente tutti i costrutti che possono comparire in una classe anonima come campi e metodi.

Un ottimo riferimento per la classe Enum è la documentazione ufficiale di Oracle.

Indice Lezione PrecedenteLezione Successiva

Pubblicato in Guide, Java, Programmazione Taggato con: , , , ,

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

*