Listado completo de tutoriales

67 - Declaración de tipos enum


Básicamente en un conjunto de constantes que se las asocia a un tipo 'enum'. En lugar de class utilizamos la palabra clave 'enum' y entre llaves definimos las constantes.

Si queremos crear un tipo enum global debemos utilizar la opción de Eclipse:

java enum global

Recordemos primero crear un proyecto y luego crear el enum:

public enum Operaciones {
    SUMA, RESTA, MULTIPLICACION, DIVISION
}

Por convención la lista de valores se escribe en mayúscula y se los separa por una coma.

Luego podemos definir una variable de tipo Operaciones:

public class PruebaEnum {
    public static void main(String[] args) {
        int valor1 = 10;
        int valor2 = 20;
        Operaciones operacion;
        operacion=Operaciones.RESTA;
        if (operacion == Operaciones.RESTA) {
            int resta = valor1 - valor2;
            System.out.println(resta);
        }
        operacion=Operaciones.SUMA;
        if (operacion == Operaciones.SUMA) {
            int suma = valor1 + valor2;
            System.out.println(suma);
        }
    }
}

Se crea una variable del tipo Operaciones sin la necesidad del operador new:

        Operaciones operacion;

Luego podemos almacenar cualquiera de los valores enumerados:

        operacion=Operaciones.RESTA;

Podemos utilizar el operador == para verificar si la variable almacena un determinado valor del enum:

        if (operacion == Operaciones.RESTA) {

Podemos cambiar en cualquier momento el valor de la variable 'operacion':

        operacion=Operaciones.SUMA;

En programas grandes el objetivo de los enum es hacer más legible un programa.

Declaración de enum dentro de una clase.

El lenguaje Java permite declarar tipos enum dentro de una clase y agregarles el modificador de acceso public o private.

Problema

Crear un proyecto y dentro del mismo crear dos clases. La primer clase se debe llamar 'Carta', declarar un enum que represente los cuatro palos del mazo y dos atributos uno del tipo de dato enum y el número de carta. Por otro lado declarar una clase llamada 'Mazo' que contenga un arreglo de 8 elementos de tipo 'Carta'. Extraer al azar una carta, mostrarla y según el tipo de palo mostrar la cantidad de puntos que gana.

Programa:

public class Carta {
    public enum Palo {
        TREBOL, DIAMANTE, CORAZON, PICA
    };

    private int numero;
    private Palo palo;

    Carta(int numero, Palo palo) {
        this.numero = numero;
        this.palo = palo;
    }

    public void imprimir() {
        System.out.println(numero + " - " + palo.toString().toLowerCase());
    }

    public Palo retornarPalo() {
        return palo;
    }

}
public class Mazo {
    private Carta[] cartas;

    Mazo() {
        cartas = new Carta[8];
        cartas[0] = new Carta(1, Carta.Palo.TREBOL);
        cartas[1] = new Carta(2, Carta.Palo.TREBOL);
        cartas[2] = new Carta(1, Carta.Palo.DIAMANTE);
        cartas[3] = new Carta(2, Carta.Palo.DIAMANTE);
        cartas[4] = new Carta(1, Carta.Palo.PICA);
        cartas[5] = new Carta(2, Carta.Palo.PICA);
        cartas[6] = new Carta(1, Carta.Palo.CORAZON);
        cartas[7] = new Carta(2, Carta.Palo.CORAZON);
    }

    public void imprimir() {
        System.out.println("Listado completo del mazo de cartas");
        for (Carta carta : cartas)
            carta.imprimir();
    }

    public void sacarUnaCartas() {
        System.out.println("Una carta elegida al azar");
        Carta carta = cartas[(int) (Math.random() * 8)];
        carta.imprimir();
        switch (carta.retornarPalo()) {
        case CORAZON:
            System.out.println("Gana 4 puntos");
            break;
        case DIAMANTE:
            System.out.println("Gana 3 puntos");
            break;
        case PICA:
            System.out.println("Gana 2 puntos");
            break;
        case TREBOL:
            System.out.println("Gana 1 puntos");
            break;
        }

    }

    public static void main(String[] ar) {
        Mazo mazo = new Mazo();
        mazo.imprimir();
        mazo.sacarUnaCartas();
    }

}

La clase carta declara con el modificador public el enum 'Palo', así podemos accederlo desde otras clases:

public class Carta {
    public enum Palo {
        TREBOL, DIAMANTE, CORAZON, PICA
    };

La clase Carta define un atributo del tipo 'Palo':

    private Palo palo;

En la clase Mazo cuando creamos cada carta pasamos al constructor una de los valores enumerados. Como el tipo de dato enumerado se encuentra en la clase Carta debemos primero disponer el nombre de la clase, seguidamente el tipo enum y finalmente la constante del tipo enum:

        cartas = new Carta[8];
        cartas[0] = new Carta(1, Carta.Palo.TREBOL);
        cartas[1] = new Carta(2, Carta.Palo.TREBOL);
        cartas[2] = new Carta(1, Carta.Palo.DIAMANTE);
        ...

Dijimos que uno de los objetivos del tipo enum es hacer nuestro programa más legible, luego para mostrar la cantidad de puntos que le corresponde según el tipo de palo podemos emplear una estructura switch:

        switch (carta.retornarPalo()) {
        case CORAZON:
            System.out.println("Gana 4 puntos");
            break;
        case DIAMANTE:
            System.out.println("Gana 3 puntos");
            break;
        case PICA:
            System.out.println("Gana 2 puntos");
            break;
        case TREBOL:
            System.out.println("Gana 1 puntos");
            break;
        }

Como vemos en cada case se compara directamente por cada uno de los valores del enum sin necesidad de anteceder el nombre del enum.

Si utilizamos if es necesario indicar nombre de clase, enum y valor:

    if (carta.retornarPalo()==Carta.Palo.CORAZON) 
        System.out.println("Gana 4 puntos");

Declaración de enum con atributos y métodos

En algunas situaciones podemos crear tipos enum que además de las constantes tengan asociados otros valores cada constante mediante atributos.

Cuando se declara un enum podemos definir constructores y otros métodos a la misma.

Problema

Declarar un tipo enum llamado 'Mes', asociar para cada constante el número de mes que corresponde.

Programa:

public enum Mes {
    ENERO(1), FEBRERO(2), MARZO(3), ABRIL(4), MAYO(5), JUNIO(6), JULIO(7), AGOSTO(8), SEPTIEMBRE(9), OCTUBRE(10),
    NOVIEMBRE(11), DICIEMBRE(12);
    private final int numero;

    Mes(int numero) {
        this.numero = numero;
    }

    public int retornarNumero() {
        return numero;
    }

}

public class PruebaEnum {
    public static void main(String[] ar) {
        Mes mes1 = Mes.AGOSTO;
        System.out.print(mes1 + " " + mes1.retornarNumero()); // AGOSTO 8
    }
}

Este ejemplo nos muestra que un enum es un tipo especial de clase que tiene una enumeración de constantes, pero puede tener asociados atributos y métodos.

Como el constructor tiene un parámetro de tipo int luego cada valor enumerado pasa al constructor un valor int:

ENERO(1)

El valor se almacena en el atributo 'numero':

    private final int numero;

Cuando definimos una variable de tipo 'Mes' almacenamos alguno de sus valores enumerados:

        Mes mes1 = Mes.AGOSTO;

Luego podemos recuperar tanto el valor del tipo enumerado como el entero asociado a dicho valor enumerado:

        System.out.print(mes1 + " " + mes1.retornarNumero()); // AGOSTO 8

Acceder a todos los valores enumerados.

Cuando se declara un enum heredamos un método llamado values que nos retorna un arreglo con todos los valores enumerados de la declaración.

Si queremos mostrar todos los nombres de meses y el número de mes que corresponde podemos modificar el proyecto anterior:

public class PruebaEnum {

    public static void main(String[] ar) {
        for (Mes mes : Mes.values())
            System.out.println(mes + " " + mes.retornarNumero());
    }

}

Tenemos un resultado similar a:

java enum values()

Recordemos que la otra forma de recorrer un arreglo en Java es a través de subíndices, la modificación del programa anterior queda:

public class PruebaEnum {

    public static void main(String[] ar) {
        Mes[] meses = Mes.values();
        for (int f = 0; f < meses.length; f++)
            System.out.println(meses[f] + " " + meses[f].retornarNumero());
    }

}

Como vemos es mucho más legible recorrer un arreglo completo para consultarlo con la primer variante de 'for'.


Retornar