CodeGym /Blog Java /Random-ES /enumeración Ejemplos prácticos. Agregar constructores y m...
Autor
Alex Vypirailenko
Java Developer at Toshiba Global Commerce Solutions

enumeración Ejemplos prácticos. Agregar constructores y métodos

Publicado en el grupo Random-ES
¡Hola! Hoy hablaremos sobre uno de los tipos de datos especiales de Java: Enum(abreviatura de "enumeración"). ¿Qué lo hace especial? Imaginemos lo que necesitamos para implementar "meses" en un programa. enumeración  Ejemplos prácticos.  Agregar constructores y métodos - 1 No parece problemático, ¿verdad? Solo necesitamos determinar qué propiedades tiene cualquier mes. Quizás primero necesitemos el nombre del mes y la cantidad de días que contiene. La solución parece bastante simple:

public class Month {

   private String name;
   private int daysCount;

   public Month(String name, int daysCount) {
       this.name = name;
       this.daysCount = daysCount;
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   public int getDaysCount() {
       return daysCount;
   }

   public void setDaysCount(int daysCount) {
       this.daysCount = daysCount;
   }

   @Override
   public String toString() {
       return "Month{" +
               "name='" + name + '\'' +
               ", daysCount=" + daysCount +
               '}';
   }
}
¡Todo el shabang! Tenemos una Monthclase, los campos requeridos, getter/setters y toString(). A menos, por supuesto, que necesitemos agregar equals()yhashCode()para alcanzar la felicidad completa :) Pero aquí tenemos un problema conceptual. Como probablemente recuerde, una de las principales ventajas de OOP es que facilita el modelado de entidades del mundo real. Una silla, un automóvil, un planeta: todos estos conceptos de la vida cotidiana se representan fácilmente en un programa con la ayuda de la abstracción. El problema es que algunas entidades del mundo real tienen un rango de valores estrictamente limitado. Solo hay 4 estaciones en un año. Hay solo 8 notas en una octava. El calendario tiene apenas 12 meses. Y Danny Ocean of Ocean's 11 tiene solo 11 amigos (aunque esto no importa :)) Lo que importa es que una clase ordinaria de Java no puede modelar estas entidades y hacer cumplir sus limitaciones naturales. NuestroMonthLa clase tiene todos los campos obligatorios. Pero si otro programador lo usa, nadie puede impedirle crear objetos completamente locos:

public class Main {

   Month month1 = new Month("lolkek", 322);
   Month month2 = new Month("yahoooooooooooo", 12345);

}
Si esto aparece en nuestro código, ¡no será fácil encontrar al culpable! Por un lado, el programador que crea los objetos podría darse cuenta de que la Monthclase significa "mes en un año" y no escribir esas tonterías. Por otro lado, el programador solo está aprovechando las habilidades que proporcionó el diseñador de la clase. ¿Es posible asignar nombres y números de días arbitrarios? Eso es exactamente lo que tenemos. ¿Qué debemos hacer entonces en esta situación? Honestamente, antes de que se lanzara Java 1.5, los programadores tenían que ser creativos :) En aquellos días, creaban estructuras como esta:

public class Month {

   private String name;
   private int daysCount;

   private Month(String name, int daysCount) {
       this.name = name;
       this.daysCount = daysCount;
   }

   public static Month JANUARY = new Month("January", 31);
   public static Month FEBRUARY = new Month("February", 28);
   public static Month MARCH = new Month("March", 31);

   @Override
   public String toString() {
       return "Month{" +
               "name='" + name + '\'' +
               ", daysCount=" + daysCount +
               '}';
   }
}
Aquí hemos reducido el número de meses de doce a tres para acortar el ejemplo. Tales diseños permitieron resolver el problema. La capacidad de crear objetos estaba limitada a un constructor privado:

private Month(String name, int daysCount) {
       this.name = name;
       this.daysCount = daysCount;
   }
Los programadores que usaban la clase no podían simplemente crear Monthobjetos. Tuvieron que usar los objetos estáticos finales proporcionados por el desarrollador de la clase. Por ejemplo, así:

public class Main {

   public static void main(String[] args) {

       Month january = Month.JANUARY;
       System.out.println(january);
   }

}
Pero, los desarrolladores de Java llamaron la atención sobre el problema existente. Por supuesto, es genial que los programadores hayan podido encontrar una solución utilizando las herramientas disponibles en el lenguaje, ¡pero no parece muy fácil! Se necesitaba una solución obvia, incluso para los novatos. Y así Enumapareció en Java. Básicamente, Enumes una clase de Java que proporciona un conjunto limitado de valores de objetos. Así es como se ve:

public enum Month {
  
   JANUARY,
   FEBRUARY,
   MARCH
}
En la definición, indicamos que Enumes una clase de Java, pero ¿es eso realmente cierto? Sí, e incluso podemos verificarlo. Por ejemplo, intente hacer que nuestra Monthenumeración herede alguna otra clase:

public abstract class AbstractMonth {
}

// Error! The extends clause cannot be used with an enum
public enum Month extends AbstractMonth {

   JANUARY,
   FEBRUARY,
   MARCH
}
¿Por qué sucede eso? Cuando escribimos:

public enum Month
el compilador convierte esta declaración en el siguiente código:

public Class Month extends Enum
Como ya sabes, Java no admite la herencia múltiple. Por lo tanto, no podemos heredar AbstractMonth. Enum¿Cómo se puede usar esta nueva construcción ? ¿Y en qué se diferencia de la construcción anterior con static finalcampos? Bueno, como ejemplo, la construcción anterior no nos permitía usar nuestro propio conjunto de valores en switchlas declaraciones. Imagina que queremos crear un programa que nos recuerde las fiestas que se celebran cada mes:

public class HolidayReminder {

   public void printHolidays(Month month) {

       switch (month) {

           // Error!
           case JANUARY:
       }
   }
}
Como puede ver, el compilador arroja un error aquí. Pero una vez que enumapareció en Java 1.5, todo se volvió mucho más simple:

public enum Month {

   JANUARY,
   FEBRUARY,
   MARCH
}

public class HolidayReminder {

   public void printHolidays(Month month) {

       switch (month) {
          
           case JANUARY:
               System.out.println("New Year's Day is January 1st!");
               break;
           case FEBRUARY:
               System.out.println("Valentine's Day is February 14th!");
               break;
           case MARCH:
               System.out.println("Saint Patrick's Day is March 17th!");
               break;
       }
   }
}


public class Main {

   public static void main(String[] args) {

       HolidayReminder reminder = new HolidayReminder();
       reminder.printHolidays(Month.JANUARY);

   }

}
Salida de la consola:

New Year's Day is January 1st!
Tenga en cuenta que el acceso a Enumlos objetos permaneció estático, tal como era antes de Java 1.5. No necesitamos crear un Monthobjeto para acceder a los meses. Cuando se trabaja con enumeraciones, es muy importante no olvidar que Enumes una clase completa. Esto significa que, si es necesario, puede definir constructores y métodos en él. Por ejemplo, en el fragmento de código anterior, simplemente especificamos los valores: ENERO, FEBRERO, MARZO. Sin embargo, podemos expandir nuestra Monthenumeración de esta manera:

public enum Month {

   JANUARY("January", 31),
   FEBRUARY("February", 28),
   MARCH("March", 31),
   APRIL("April", 30),
   MAY("May", 31),
   JUNE("June", 30),
   JULY("July", 31),
   AUGUST("August", 31),
   SEPTEMBER("September", 30),
   OCTOBER("October", 31),
   NOVEMBER("November", 30),
   DECEMBER("December", 31);

   private String name;
   private int daysCount;

   Month(String name, int daysCount) {
       this.name = name;
       this.daysCount = daysCount;
   }

   public static Month[] getWinterMonths() {

       return new Month[]{DECEMBER, JANUARY, FEBRUARY};
   }

   public static Month[] getSummerMonths() {

       return new Month[]{JUNE, JULY, AUGUST};
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   public int getDaysCount() {
       return daysCount;
   }

   public void setDaysCount(int daysCount) {
       this.daysCount = daysCount;
   }

   @Override
   public String toString() {
       return "Month{" +
               "name='" + name + '\'' +
               ", daysCount=" + daysCount +
               '}';
   }
}
Aquí le dimos a nuestros enum2 campos (el nombre del mes y el número de días), un constructor que usa estos campos, getter/setters, el toString()método y 2 métodos estáticos. Como puede ver, no hubo problemas con esto. Nuevamente, Enumrealmente es una clase completa:

import java.util.Arrays;

public class Main {

   public static void main(String[] args) {

       System.out.println(Arrays.toString(Month.getSummerMonths()));

   }

}
Salida de la consola:

[Month{name='June', daysCount=30}, Month{name='July', daysCount=31}, Month{name='August', daysCount=31}]
Finalmente, quiero recomendar un libro de Java extremadamente útil, a saber, "Effective Java" de Joshua Bloch . enumeración  Ejemplos prácticos.  Agregar constructores y métodos - 3El autor es uno de los creadores de Java, por lo que definitivamente puede confiar en sus consejos sobre cómo usar correctamente y de manera competente las herramientas del lenguaje :) Con respecto a nuestra lección, le recomiendo que preste especial atención al capítulo del libro sobre Enum. ¡Feliz lectura! :)
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION