Hay un método de valores en la enumeración que se usa para generar una matriz en el orden definido por la enumeración, que se puede usar para recorrer. Todas nuestras clases de enumeración personalizadas heredan de java.lang.Enum y tienen las siguientes funciones en los ejemplos:
Copie el código de código de la siguiente manera:
//: enumerado/EnumClass.java
// Capacidades de la clase Enum
importar estática net.mindview.util.Print.*;
enum Arbustos {TIERRA, ARRASTRE, COLGANTE}
clase pública EnumClass {
público estático vacío principal (String [] argumentos) {
for(Arbustos s: Arbustos.valores()) {
print(s + " ordinal: " + s.ordinal());
printnb(s.compareTo(Arbustos.CRAWLING) + " ");
printnb(s.equals(Arbustos.CRAWLING) + " ");
print(s == Arbustos.CRAWLING);
print(s.getDeclaringClass());
print(s.nombre());
imprimir("----------------------");
}
// Producir un valor de enumeración a partir de un nombre de cadena:
for(String s: "TERRENO ARRASTRE COLGANTE".split(" ")) {
Arbusto arbustivo = Enum.valueOf(Srubbery.class, s);
imprimir(arbusto);
}
}
} /* Producción:
Ordinal de TIERRA: 0
-1 falso falso
clase de arbusto
Joshua Bloch fue de gran ayuda en el desarrollo de este capítulo.
SUELO
-----------------------
ordinal ARRASTRE: 1
verdad verdad
clase de arbusto
ARRASTRE
-----------------------
Ordinal COLGANTE: 2
falso falso
clase de arbusto
COLGANTE
-----------------------
COLGANTE
ARRASTRE
SUELO
*///:~
También podemos usar referencias de enumeración estáticas:
Copie el código de código de la siguiente manera:
//: enumerado/Spiciness.java
paquete enumerado;
enumeración pública Picante {NO, SUAVE, MEDIO, CALIENTE, LLAMEANTE} ///:~
//: enumerado/Burrito.java
paquete enumerado;
importar estática enumerada.Spiciness.*;
Burrito de clase pública {
Grado de picante;
Burrito público (grado de picante) { this.grado = grado;}
public String toString() { return "Burrito es "+ grado;}
público estático vacío principal (String [] argumentos) {
System.out.println(nuevo Burrito(NO));
System.out.println(nuevo Burrito(MEDIO));
System.out.println(nuevo Burrito(CALIENTE));
}
} /* Producción:
El burrito NO es
El burrito es MEDIANO
El burrito está CALIENTE
*///:~
Además de agregar métodos a una enumeración, que no se pueden heredar, la enumeración se puede tratar como una clase general, lo que significa que puede agregar métodos a la enumeración y también puede definir el método principal en la enumeración:
Copie el código de código de la siguiente manera:
//: enumerado/OzWitch.java
// Las brujas en la tierra de Oz.
importar estática net.mindview.util.Print.*;
enumeración pública OzWitch {
// Las instancias deben definirse primero, antes de los métodos:
OESTE("Miss Gulch, también conocida como la Bruja Malvada del Oeste"), NORTE("Glinda, la Bruja Buena del Norte"), ESTE("Bruja Malvada del Este, portadora del Rubí" + "Zapatillas, aplastadas por La casa de Dorothy"),SOUTH("Bueno por inferencia, pero falta");
descripción de cadena privada;
// El constructor debe ser paquete o acceso privado:
OzWitch privada (descripción de cadena) {
this.descripción = descripción;
}
cadena pública getDescription() {devolver descripción;
público estático vacío principal (String [] argumentos) {
para (bruja OzWitch: OzWitch.values())
print(bruja + ": " + bruja.getDescription());
}
} /* Producción:
OESTE: Miss Gulch, también conocida como la Bruja Malvada del Oeste
NORTE: Glinda, la Bruja Buena del Norte
ESTE: Bruja Malvada del Este, portadora de las Zapatillas de Rubí, aplastada por la casa de Dorothy.
SUR: Bueno por inferencia, pero falta
*///:~
Copie el código de código de la siguiente manera:
//: enumerado/SpaceShip.java
enumeración pública Nave espacial {
EXPLORADOR, CARGA, TRANSPORTE, CRUCERO, ACORAZADO, NAVE NODRIZA;
cadena pública toString() {
ID de cadena = nombre();
Cadena inferior = id.substring(1).toLowerCase();
devolver id.charAt(0) + inferior;
}
público estático vacío principal (String [] argumentos) {
for(Nave espacial s: valores()) {
System.out.println(s);
}
}
} /* Producción:
Explorar
Carga
Transporte
Crucero
Acorazado
Nave nodriza
*///:~
Enumeraciones en declaraciones de cambio Una función importante de las enumeraciones es en las declaraciones de cambio. Por lo general, las declaraciones de cambio solo funcionan con valores enteros, pero hay un orden incorporado de los números enteros en las enumeraciones, por lo que el orden de las instancias se puede determinar mediante algún método. entonces las enumeraciones se pueden usar en declaraciones de cambio:
Copie el código de código de la siguiente manera:
//: enumerado/TrafficLight.java
// Enumeraciones en sentencias de cambio.
importar estática net.mindview.util.Print.*;
// Definir un tipo de enumeración:
enum Señal {VERDE, AMARILLO, ROJO,}
clase pública Semáforo {
Color de señal = Señal.ROJO;
cambio de vacío público () {
cambiar(color) {
// Ten en cuenta que no tienes que decir Signal.RED
// en la declaración del caso:
caso ROJO: color = Señal.VERDE;
romper;
caso VERDE: color = Señal.AMARILLO;
romper;
caso AMARILLO: color = Señal.ROJO;
romper;
}
}
cadena pública toString() {
devolver "El semáforo es" + color;
}
público estático vacío principal (String [] argumentos) {
Semáforo t = nuevo Semáforo();
para(int i = 0; i < 7; i++) {
imprimir(t);
t.cambio();
}
}
} /* Producción:
El semáforo está en ROJO
El semáforo está en VERDE.
El semáforo está en AMARILLO
El semáforo está en ROJO
El semáforo está en VERDE.
El semáforo está en AMARILLO
El semáforo está en ROJO
*///:~
El secreto de los valores () Aunque usamos el método de valores antes, si miramos Enum, no encontramos el método de valores. Entonces, ¿hay otros métodos ocultos? Podemos comprobarlo con un simple código de reflexión:
Copie el código de código de la siguiente manera:
//: enumerado/Reflexión.java
// Analizando enumeraciones usando la reflexión.
importar java.lang.reflect.*;
importar java.util.*;
importar net.mindview.util.*;
importar estática net.mindview.util.Print.*;
enum Explorar {AQUÍ, ALLÍ}
Reflexión de clase pública {
conjunto estático público <String> analizar (Clase <?> enumClass) {
print("----- Analizando " + enumClass + " -----");
imprimir("Interfaces:");
para (Tipo t: enumClass.getGenericInterfaces())
imprimir(t);
print("Base: " + enumClass.getSuperclass());
print("Métodos: ");
Set<String> métodos = new TreeSet<String>();
para (Método m: enumClass.getMethods())
métodos.add(m.getName());
imprimir(métodos);
métodos de devolución;
}
público estático vacío principal (String [] argumentos) {
Establecer<String> exploreMethods = analizar(Explore.class);
Establecer<String> enumMethods = analizar(Enum.class);
print("Explorar.contieneTodo(Enumeración)? " +
exploreMethods.containsAll(enumMethods));
printnb("Explorar.removeAll(Enum): ");
exploreMethods.removeAll(enumMethods);
print(explorarMétodos);
// Descompila el código de la enumeración:
OSExecute.command("explorar javap");
}
} /* Producción:
----- Analizando clase Explorar -----
Interfaces:
Base: clase java.lang.Enum
Métodos:
[compareTo, es igual, getClass, getDeclaringClass, hashCode, nombre, notificar, notificar a todos, ordinal, toString, valueOf, valores, esperar]
----- Analizando la clase java.lang.Enum -----
Interfaces:
java.lang.Comparable<E>
interfaz java.io.Serializable
Base: clase java.lang.Object
Métodos:
[comparar con, igual a, getClass, getDeclaringClass, hashCode, nombre, notificar, notificar a todos, ordinal, toString, valueOf, esperar]
Explore.containsAll(Enum)?
Explorar.removeAll(Enum): [valores]
Compilado de "Reflection.java"
La clase final Explore extiende java.lang.Enum{
final estático público Explora AQUÍ;
público estático final Explora ALLÍ;
valores públicos estáticos finales Explorar [] ();
valor de exploración estática pública de (java.lang.String);
estático {};
}
*///:~
Podemos ver que el compilador agrega el método de valores. El compilador también agrega el método valueOf al crear la enumeración, pero también hay un método valueOf en la clase Enum, pero este método tiene dos parámetros, mientras que el método valueOf agregado por el compilador tiene solo un parámetro. El compilador interpreta las enumeraciones como finales, por lo que no se pueden heredar. Debido a que el método de valores es un método estático agregado por el compilador, si convierte la enumeración a Enum, el método de valores no estará disponible, pero hay un método getEnumConstants en Class, por lo que aunque el método de valores es no está disponible en Enum, pero aún puedes obtener la instancia de enumeración a través del objeto Class:
Copie el código de código de la siguiente manera:
//: enumerado/UpcastEnum.java
// No hay método de valores() si actualizas una enumeración
enum Buscar {AQUÍ, ABAJO}
clase pública UpcastEnum {
público estático vacío principal (String [] argumentos) {
Buscar[] vals = Buscar.valores();
Enum e = Buscar.AQUÍ // Upcast;
// e.values(); // Sin valores() en Enum
for(Enum es: e.getClass().getEnumConstants())
System.out.println(es);
}
} /* Producción:
AQUÍ
AQUÉL
*///:~
Implementación sin herencia Debido a que todos los tipos de enumeración que definimos heredan de java.lang.Enum, y Java no admite herencia múltiple, las enumeraciones no se crean mediante herencia, pero se pueden crear heredando una o más interfaces:
Copie el código de código de la siguiente manera:
//: enumerados/cartoons/EnumImplementation.java
// Una enumeración puede implementar una interfaz
paquete enumerado.cartoons;
importar java.util.*;
importar net.mindview.util.*;
enum CartoonCharacter implementa Generator<CartoonCharacter> {
SLAPPY, SPANKY, PUNCHY, TONTO, Hinchable, NUTY, BOB;
rand aleatorio privado = nuevo aleatorio (47);
personaje de dibujos animados público siguiente() {
valores de retorno()[rand.nextInt(valores().longitud)];
}
}
clase pública EnumImplementation {
público estático <T> void printNext(Generador<T> rg) {
System.out.print(rg.next() + ", ");
}
público estático vacío principal (String [] argumentos) {
// Elige cualquier instancia:
CaricaturaCharacter cc = CaricaturaCharacter.BOB;
para(int i = 0; i < 10; i++)
imprimirSiguiente(cc);
}
} /* Producción:
BOB, PUNCHY, BOB, SPANKY, NUEZ, PUNCHY, SLAPPY, NUEZ, NUEZ, SLAPPY,
*///:~
Selección aleatoria En muchos de nuestros ejemplos posteriores, seleccionaremos objetos aleatoriamente de instancias de enumeración. Creamos una clase pública para implementar esto:
Copie el código de código de la siguiente manera:
//: net/mindview/util/Enums.java
paquete net.mindview.util;
importar java.util.*;
Enumeraciones de clase pública {
rand aleatorio estático privado = nuevo aleatorio (47);
público estático <T extiende Enum<T>> T aleatorio(Clase<T> ec) {
devolver aleatorio(ec.getEnumConstants());
}
público estático <T> T aleatorio (valores T[]) {
valores de retorno [rand.nextInt (valores.longitud)];
}
} ///:~
Copie el código de código de la siguiente manera:
//: enumerado/RandomTest.java
importar net.mindview.util.*;
enum Actividad { SENTADO, ACOSTADO, DE PIE, SALTO, CORRER, ESQUIVAR, SALTAR, CAER, VOLAR }
prueba aleatoria de clase pública {
público estático vacío principal (String [] argumentos) {
para(int i = 0; i < 20; i++)
System.out.print(Enums.random(Actividad.clase) + " ");
}
} /* Producción:
DE PIE VOLAR CORRER DE PIE CORRER DE PIE ACOSTADO ESQUIVAR SENTADO CORRER SALTAR SALTAR SALTAR CORRER DE PIE Tumbado CAER CORRER VOLAR Tumbado
*///:~
El uso de interfaces para organizar enumeraciones no se puede heredar, lo que a veces nos causa inconvenientes, porque a veces queremos expandir el número de enumeraciones a través de la herencia y, a veces, necesitamos agrupar enumeraciones. Para este último, podemos definir enumeraciones agrupadas dentro de la interfaz y luego crear la enumeración heredando de esta interfaz. De la siguiente manera, tenemos diferentes categorías de alimentos que deben crearse como enumeraciones, pero debemos definir cada categoría como tipos. de Alimentos son los siguientes:
Copie el código de código de la siguiente manera:
//: enumerado/menú/Food.java
// Subcategorización de enumeraciones dentro de interfaces.
paquete enumerado.menu;
interfaz pública Comida {enum Aperitivo implementa Comida {ENSALADA, SOPA, SPRING_ROLLS;}
enum MainCourse implementa Alimentos {LASAÑA, BURRITO, PAD_THAI, LENTEJAS, HUMMOUS, VINDALOO;}
enum Implementos de postre Comida {TIRAMISU, GELATO, BLACK_FOREST_CAKE,FRUIT, CREME_CARAMEL;}
enum Implementos de café Alimentos {BLACK_COFFEE, DECAF_COFFEE, ESPRESSO,LATTE, CAPPUCCINO, TEA, HERB_TEA;}
} ///:~
Debido a que cada enumeración se define como una implementación de una interfaz, cada enumeración es de tipo Comida, de la siguiente manera:
Copie el código de código de la siguiente manera:
//: enumerado/menú/TypeOfFood.java
paquete enumerado.menu;
importar estático enumerado.menu.Food.*;
clase pública TipoDeComida {
público estático vacío principal (String [] argumentos) {
Comida comida = Aperitivo.ENSALADA;
comida = Plato Principal.LASAÑA;
comida = Postre.GELATO;
comida = Café.CAPPUCCINO;
}
} ///:~
Pero las interfaces no pueden operar en múltiples tipos como enumeraciones, por lo que si necesita una enumeración de enumeraciones, puede encapsular una instancia de cada tipo de enumeración en una enumeración:
Copie el código de código de la siguiente manera:
//: enumerado/menú/Curso.java
paquete enumerado.menu;
importar net.mindview.util.*;
Curso de enumeración pública {
APERITIVO(Comida.Aperitivo.clase),PLATO PRINCIPAL(Comida.Curso Principal.clase),POSTRE(Comida.Postre.clase),CAFÉ(Comida.Café.clase);
valores privados de alimentos [];
Curso privado(Clase<? extiende Comida> tipo) {
valores = kind.getEnumConstants();
}
Selección aleatoria de comida pública() {
devolver Enums.random(valores);
}
} ///:~
Cada enumeración usa el objeto Class como parámetro constructor correspondiente. Podemos usar getEnumConstants de este parámetro para obtener la instancia de enumeración. Esta instancia se puede usar en el método randomSelection para generar comidas aleatorias.
Copie el código de código de la siguiente manera:
//: enumerado/menú/Meal.java
paquete enumerado.menu;
comida de clase pública {
público estático vacío principal (String [] argumentos) {
para(int i = 0; i < 5; i++) {
for(Curso curso: Curso.valores()) {
Comida comida = curso.randomSelection();
System.out.println(comida);
}
System.out.println("---");
}
}
} /* Producción:
ROLLOS DE PRIMAVERA
VINDALOO
FRUTA
CAFÉ DECAF
---
SOPA
VINDALOO
FRUTA
TÉ
---
ENSALADA
BURRITO
FRUTA
TÉ
---
ENSALADA
BURRITO
CREMA_CARAMELO
LATTE
---
SOPA
BURRITO
TIRAMISÚ
CAFÉ EXPRÉS
---
*///:~
Aquí hay una implementación más compacta:
Copie el código de código de la siguiente manera:
//: enumerado/SecurityCategory.java
// Subcategorización de enumeraciones más concisa.
importar net.mindview.util.*;
enumeración Categoría de seguridad {
ACCIONES(Seguridad.Clase.Acciones), BONOS(Seguridad.Clase.Bonos);
Valores de seguridad[];
SecurityCategory(Clase<? extiende Seguridad> tipo) {
valores = kind.getEnumConstants();
}
interfaz de seguridad {
enum Stock implementa Seguridad { CORTO, LARGO, MARGEN }
enum Bond implementa Seguridad { MUNICIPAL, BASURA }
}
Selección aleatoria de seguridad pública() {
devolver Enums.random(valores);
}
público estático vacío principal (String [] argumentos) {
para(int i = 0; i < 10; i++) {
Categoría SecurityCategory = Enums.random(SecurityCategory.class);
System.out.println(categoría + ": " +
categoría.randomSelection());
}
}
} /* Producción:
BONO: MUNICIPAL
BONO: MUNICIPAL
STOCK: MARGEN
STOCK: MARGEN
VÍNCULO: BASURA
STOCK: CORTO
STOCK: LARGO
STOCK: LARGO
BONO: MUNICIPAL
VÍNCULO: BASURA
*///:~
Copie el código de código de la siguiente manera:
//: enumerado/menú/Meal2.java
paquete enumerado.menu;
importar net.mindview.util.*;
enumeración pública Comida2 {
APERITIVO(Comida.Aperitivo.clase),PLATO PRINCIPAL(Comida.Curso Principal.clase),POSTRE(Comida.Postre.clase),CAFÉ(Comida.Café.clase);
valores privados de alimentos [];
Comida2 privada(Clase<? extiende Comida> tipo) {
valores = kind.getEnumConstants();
}
interfaz pública Comida {
enum Aperitivo implementa Comida {ENSALADA, SOPA, ROLLOS DE PRIMAVERA;}
enum MainCourse implementa Alimentos {LASAÑA, BURRITO, PAD_THAI, LENTEJAS, HUMMOUS, VINDALOO;}
enum Implementos de postre Comida {TIRAMISU, GELATO, BLACK_FOREST_CAKE,FRUIT, CREME_CARAMEL;}
enum Implementos de café Alimentos {BLACK_COFFEE, DECAF_COFFEE, ESPRESSO,LATTE, CAPPUCCINO, TEA, HERB_TEA;}
}
Selección aleatoria de comida pública() {
devolver Enums.random(valores);
}
público estático vacío principal (String [] argumentos) {
para(int i = 0; i < 5; i++) {
para (comida2: comida2.valores()) {
Comida comida = comida.randomSelection();
System.out.println(comida);
}
System.out.println("---");
}
}
} /* Misma salida que Meal.java *///:~
Utilice EnumSet en lugar de indicadores EnumSet se agregó en Java SE5 para combinar enumeraciones y conjuntos para reemplazar indicadores de bits basados en números enteros. Las banderas de bits generalmente se usan para indicar el cambio de algún tipo de información, pero en el código, los bits funcionan en lugar de conceptos significativos, por lo que no son fáciles de entender. EnumSet es más rápido que las banderas de bits. Utiliza long internamente para representar un vector de bits, y luego puede usar un lenguaje más conceptual para representar el cambio de un determinado bit sin preocuparse por la eficiencia. Los elementos de EnumSet deben provenir de la misma enumeración. A continuación se define una enumeración de la posición de la alarma:
Copie el código de código de la siguiente manera:
//: enumerados/AlarmPoints.java
paquete enumerado;
enumeración pública Puntos de alarma {ESCALERA1, ESCALERA2, VESTÍBULO, OFICINA1, OFICINA2, OFICINA3, OFICINA4, BAÑO, SERVICIOS PÚBLICOS, COCINA} ///:~
Luego use la clase EnumSet para rastrear el estado de la alarma:
Copie el código de código de la siguiente manera:
//: enumerado/EnumSets.java
// Operaciones en EnumSets
paquete enumerado;
importar java.util.*;
importar estática enumerada.AlarmPoints.*;
importar estática net.mindview.util.Print.*;
conjuntos de enumeraciones de clase pública {
público estático vacío principal (String [] argumentos) {
EnumSet<AlarmPoints> puntos = EnumSet.noneOf(AlarmPoints.class // Conjunto vacío);
puntos.add(BAÑO);
imprimir(puntos);
puntos.addAll(EnumSet.of(ESCALERA1, ESCALERA2, COCINA));
imprimir(puntos);
puntos = EnumSet.allOf(AlarmPoints.class);
puntos.removeAll(EnumSet.of(ESCALERA1, ESCALERA2, COCINA));
imprimir(puntos);
puntos.removeAll(EnumSet.range(OFICINA1, OFICINA4));
imprimir(puntos);
puntos = EnumSet.complementOf(puntos);
imprimir(puntos);
}
} /* Producción:
[BAÑO]
[ESCALERA1, ESCALERA2, BAÑO, COCINA]
[VESTÍBULO, OFICINA1, OFICINA2, OFICINA3, OFICINA4, BAÑO, SERVICIOS PÚBLICOS]
[VESTÍBULO, BAÑO, SERVICIOS PÚBLICOS]
[ESCALERA1, ESCALERA2, OFICINA1, OFICINA2, OFICINA3, OFICINA4, COCINA]
*///:~
EnumSet se basa en tipos largos y tiene 64 bits, entonces, ¿qué pasa si nuestro tipo de enumeración excede este número?
Copie el código de código de la siguiente manera:
//: enumerado/BigEnumSet.java
importar java.util.*;
clase pública BigEnumSet {
enumeración Grande { A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23 , A24, A25, A26, A27, A28, A29, A30, A31, A32,
A33, A34, A35, A36, A37, A38, A39, A40, A41, A42, A43, A44, A45, A46, A47, A48, A49, A50, A51, A52, A53, A54, A55, A56, A57, A58, A59, A60, A61, A62, A63, A64, A65,
A66, A67, A68, A69, A70, A71, A72, A73, A74, A75}
público estático vacío principal (String [] argumentos) {
EnumSet<Grande> bigEnumSet = EnumSet.allOf(Grande.clase);
System.out.println(bigEnumSet);
}
} /* Producción:
[A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23, A24 , A25, A26, A27, A28, A29, A30, A31, A32, A33, A34, A35, A36, A37, A38, A39, A40, A41, A42, A43, A44, A45, A46, A47, A48, A49, A50, A51, A52, A53, A54, A55, A56, A57, A58, A59, A60, A61, A62, A63, A64, A65, A66, A67, A68, A69, A70, A71, A72, A73, A74, A75]
*///:~
Podemos ver que el programa se está ejecutando normalmente, por lo que es muy probable que se haya agregado internamente un tipo largo para ayudar a acomodar el tipo de enumeración usando EnumMap.
EnumMap es un tipo especial de Map. El valor de su clave solo puede ser el tipo en la misma enumeración. Debido a esto, EnumMap se puede implementar internamente a través de una matriz, lo cual es muy eficiente.
Copie el código de código de la siguiente manera:
//: enumerado/EnumMaps.java
// Conceptos básicos de EnumMaps.
paquete enumerado;
importar java.util.*;
importar estática enumerada.AlarmPoints.*;
importar estática net.mindview.util.Print.*;
Comando de interfaz {acción nula();
clase pública EnumMaps {
público estático vacío principal (String [] argumentos) {
EnumMap<AlarmPoints,Command> em = new EnumMap<AlarmPoints,Command>(AlarmPoints.class);
em.put(COCINA, nuevo comando() {
acción nula pública() { print("¡Fuego en la cocina!");
});
em.put(BAÑO, nuevo Comando() {
acción nula pública() { print("¡Alerta de baño!");
});
for(Map.Entry<Puntos de alarma,Comando> e: em.entrySet()) {
printnb(e.getKey() + ": ");
e.getValue().action();
}
try { // Si no hay ningún valor para una clave en particular:
em.get(UTILIDAD).action();
} captura (Excepción e) {
imprimir(e);
}
}
} /* Producción:
BAÑO: ¡Alerta de baño!
COCINA: ¡Fuego en la cocina!
java.lang.NullPointerException
*///:~
Las enumeraciones Java de métodos constantes específicos tienen una característica muy interesante, es decir, se pueden definir diferentes comportamientos para cada instancia de enumeración. Para lograr esto, definimos uno o más métodos abstractos como parte de la enumeración y luego definimos diferentes comportamientos para cada uno. instancia de enumeración. Un método de definición de instancia de enumeración:
Copie el código de código de la siguiente manera:
//: enumerado/ConstantSpecificMethod.java
importar java.util.*;
importar java.texto.*;
enumeración pública Método específico constante {
DATE_TIME {String getInfo() {return DateFormat.getDateInstance().format(nueva Fecha());}},
CLASSPATH {String getInfo() {return System.getenv("CLASSPATH");}},
VERSIÓN {String getInfo() {return System.getProperty("java.version");}};
cadena abstracta getInfo();
público estático vacío principal (String [] argumentos) {
para(ConstantSpecificMethod csm: valores())
System.out.println(csm.getInfo());
}
} /* (Ejecutar para ver el resultado) *///:~
El código anterior parece estar atascado en que cada elemento de enumeración es un elemento diferente y todos los elementos heredan de la clase base ConstantSpecificMethod, pero realmente no podemos entenderlo de esta manera, porque no podemos tratar los elementos de enumeración como tipos:
Copie el código de código de la siguiente manera:
//: enumerado/NotClasses.java
// {Ejecutivo: javap -c LikeClasses}
importar estática net.mindview.util.Print.*;
enum LikeClasses {WINKEN { comportamiento vacío() { print("Comportamiento1"); PARPADEAR { comportamiento vacío() { print("Comportamiento2" } }, NOD { comportamiento vacío() { print("Comportamiento3") ; } };
comportamiento vacío abstracto();
}
clase pública NotClasses {
// void f1(instancia LikeClasses.WINKEN) {} // No
} /* Producción:
Compilado de "NotClasses.java"
clase abstracta LikeClasses extiende java.lang.Enum{
LikeClasses finales estáticas públicas WINKEN;
LikeClasses finales estáticas públicas BLINKEN;
LikeClasses finales estáticas públicas NOD;
...
*///:~
Considere otro ejemplo. Hay un menú de lavado de autos. Los clientes eligen diferentes servicios según diferentes menús. Puede usar métodos constantes específicos para asociar el menú con los servicios y usar EnumSet para mantener las opciones del cliente, de la siguiente manera:
Copie el código de código de la siguiente manera:
//: enumerado/CarWash.java
importar java.util.*;
importar estática net.mindview.util.Print.*;
Lavado de autos de clase pública {
ciclo de enumeración pública {BAJOS {acción vacía() { print("Rociando los bajos" }},
LAVADO DE RUEDAS {void action() { print("Lavado de ruedas" }},
PRELAVADO {void action() { print("Aflojando la suciedad" }},
BÁSICO {acción nula() { print("El lavado básico" }},
HOTWAX {void action() { print("Aplicar cera caliente" }},
ENJUAGAR {acción anulada() { print("Enjuague" }},
SECADO {acción nula() { print("Soplado" }};
acción nula abstracta();
}
EnumSet<Ciclo> ciclos = EnumSet.of(Cycle.BASIC, Cycle.RINSE);
public void add(Ciclo ciclo) { ciclos.add(ciclo });
lavado de vacío público() {
para (Ciclo c: ciclos)
c.acción();
}
cadena pública toString() { return ciclos.toString();
público estático vacío principal (String [] argumentos) {
Lavado de Autos = nuevo Lavado de Autos();
imprimir(lavar);
lavar.lavarCoche();
// El orden de adición no es importante:
wash.add(Ciclo.SECADO);
wash.add(Cycle.BLOWDRY); // Duplicados ignorados
wash.add(Ciclo.ENJUAGUE);
wash.add(Ciclo.HOTWAX);
imprimir(lavar);
lavar.lavarCoche();
}
} /* Producción:
[BÁSICO, ENJUAGUE]
El lavado básico
Enjuague
[BÁSICO, CERA CALIENTE, ENJUAGUE, SECADO]
El lavado básico
Aplicar cera caliente
Enjuague
Secar con secador
*///:~
También podemos anular los métodos constantes específicos predeterminados en lugar de utilizar métodos abstractos heredados, de la siguiente manera:
Copie el código de código de la siguiente manera:
//: enumerado/OverrideConstantSpecific.java
importar estática net.mindview.util.Print.*;
enumeración pública OverrideConstantSpecific {
TUERCA, PERNO, ARANDELA {void f() { print("Método anulado" }};
void f() { print("comportamiento predeterminado");
público estático vacío principal (String [] argumentos) {
for(OverrideConstantSpecific ocs: valores()) {
printnb(ocs + ": ");
ocs.f();
}
}
} /* Producción:
TUERCA: comportamiento predeterminado
BOLT: comportamiento predeterminado
ARANDELA: Método anulado
*///:~
A veces queremos pasar solicitudes específicas en la cadena. Saber que un objeto en la cadena puede manejar la solicitud se puede lograr fácilmente mediante el uso de métodos constantes específicos. El siguiente es un ejemplo de procesamiento de correos electrónicos.
Copie el código de código de la siguiente manera:
//: enumerado/Oficina de Correos.java
// Modelado de una oficina de correos.
Tipos enumerados 743
importar java.util.*;
importar net.mindview.util.*;
importar estática net.mindview.util.Print.*;
clase correo {
// Los NO reducen la probabilidad de selección aleatoria:
enumeración Entrega general {SÍ,NO1,NO2,NO3,NO4,NO5}
enum Capacidad de escaneo {UNSCANNABLE,YES1,YES2,YES3,YES4}
enumeración Legibilidad {ILLEGIBLE,YES1,YES2,YES3,YES4}
dirección de enumeración {INCORRECTO,OK1,OK2,OK3,OK4,OK5,OK6}
enumeración Dirección de retorno {FALTA, OK1, OK2, OK3, OK4, OK5}
Entrega generalEntrega general;
Escaneabilidad escaneabilidad;
Legibilidad legibilidad;
Dirección de dirección;
Dirección de retorno dirección de retorno;
contador largo estático = 0;
identificación larga = contador++;
public String toString() { return "Correo " + id }
detalles de cadena pública() {
return toString() + ", Entrega general: " + entrega general + ", Escaneabilidad de direcciones: " + escaneabilidad + ", Legibilidad de direcciones: " + legibilidad +
", Dirección Dirección: " + dirección + ", Dirección de devolución: " + dirección de devolución;
}
//Generar correo de prueba:
Correo estático público randomMail() {
Correo m = nuevo correo();
m.generalDelivery= Enums.random(GeneralDelivery.clase);
m.scannability = Enums.random(Scannability.class);
m.readability = Enums.random(Readability.class);
m.dirección = Enums.random(Dirección.clase);
m.returnAddress = Enums.random(ReturnAddress.clase);
devolver m;
}
generador de iterable <correo> estático público (recuento de int final) {
devolver nuevo Iterable<Correo>() {
int n = contar;
Iterador público<Correo> iterador() {
devolver nuevo iterador<correo>() {
public boolean hasNext() { return n-- > 0 }
Correo público siguiente() { return correo aleatorio();
public void remove() { // No implementado
lanzar nueva UnsupportedOperationException();
}
};
}
};
}
}
oficina de correos de clase pública {
enumeración MailHandler {
ENTREGA_GENERAL {
identificador booleano (correo m) {
cambiar(m.entregageneral) {
caso SÍ:
print("Usando entrega general para " + m);
devolver verdadero;
predeterminado: devuelve falso;
}
}
},
MÁQUINA_ESCANEO {
identificador booleano (correo m) {
cambiar(m.escanabilidad) {
caso UNSCNNABLE: devuelve falso;
por defecto:
cambiar(m.dirección) {
caso INCORRECTO: devuelve falso;
por defecto:
print("Entregando "+ m + " automáticamente");
devolver verdadero;
}
}
}
},
VISUAL_INSPECCIÓN {
identificador booleano (correo m) {
cambiar(m.legibilidad) {
caso ILEGIBLE: devuelve falso;
por defecto:
cambiar(m.dirección) {
caso INCORRECTO: devuelve falso;
por defecto:
print("Entregando " + m + " normalmente");
devolver verdadero;
}
}
}
},
RETURN_TO_SENDER {
identificador booleano (correo m) {
cambiar(m.returnAddress) {
caso FALTANTE: devuelve falso;
por defecto:
print("Devolviendo " + m + " al remitente");
devolver verdadero;
}
}
};
identificador booleano abstracto (Correo m);
}
identificador de vacío estático (correo m) {
para (controlador de MailHandler: MailHandler.values())
si(controlador.controlador(m))
devolver;
print(m + "es letra muerta");
}
público estático vacío principal (String [] argumentos) {
for(Correo electrónico: Mail.generator(10)) {
imprimir(correo.detalles());
manejar(correo);
imprimir("*****");
}
}
} /* Producción:
Correo 0, Entrega general: NO2, Escaneabilidad de dirección: NO ESCANABLE, Legibilidad de dirección: SÍ3, Dirección Dirección: OK1, Dirección de remitente: OK1
Entregando correo 0 normalmente
*****
Correo 1, Entrega general: NO5, Escaneabilidad de dirección: SÍ3, Legibilidad de dirección: ILEGIBLE, Dirección Dirección: OK5, Dirección de remitente: OK1
Entregando correo 1 automáticamente
*****
Correo 2, entrega general: SÍ, capacidad de escaneo de direcciones: SÍ3, legibilidad de direcciones: SÍ1, dirección de dirección: OK1, dirección de remitente: OK5
Uso de entrega general para Mail 2
*****
Correo 3, Entrega general: NO4, Escaneabilidad de dirección: SÍ3, Legibilidad de dirección: SÍ1, Dirección Dirección: INCORRECTA, Dirección de remitente: OK4
Devolver el correo 3 al remitente
*****
Correo 4, Entrega general: NO4, Escaneabilidad de dirección: NO ESCANABLE, Legibilidad de dirección: SÍ1, Dirección Dirección: INCORRECTA, Dirección de remitente: OK2
Devolver el correo 4 al remitente
*****
Correo 5, Entrega general: NO3, Escaneabilidad de dirección: SÍ1, Legibilidad de dirección: ILEGIBLE, Dirección Dirección: OK4, Dirección de remitente: OK2
Entregar Mail 5 automáticamente
*****
Correo 6, Entrega general: SÍ, Escaneabilidad de dirección: SÍ4, Legibilidad de dirección: ILEGIBLE, Dirección Dirección: OK4, Dirección de remitente: OK4
Uso de la entrega general para Mail 6
*****
Correo 7, Entrega general: SÍ, Escaneabilidad de dirección: SÍ3, Legibilidad de dirección: SÍ4, Dirección de dirección: OK2, Dirección de remitente: FALTA
Uso de la entrega general para Mail 7
*****
Correo 8, Entrega general: NO3, Escanabilidad de dirección: SÍ1, Legibilidad de dirección: SÍ3, Dirección Dirección: INCORRECTA, Dirección de remitente: FALTA
El correo 8 es letra muerta
*****
Correo 9, Entrega general: NO1, Escaneabilidad de dirección: NO ESCANABLE, Legibilidad de dirección: SÍ2, Dirección Dirección: OK1, Dirección de remitente: OK4
Entregando correo 9 normalmente
*****
*///:~
El tipo de enumeración también es un tipo ideal para crear una máquina de estados. Una máquina de estados puede moverse entre un número limitado de estados según la entrada y luego finalizar el trabajo después de que se cumpla un determinado estado. Además, cada estado tendrá un. La salida correspondiente es una máquina expendedora. Un ejemplo de una máquina de estados típica donde definimos diferentes entradas dentro de una enumeración:
Copie el código de código de la siguiente manera:
//: enumerado/Input.java
paquete enumerado;
importar java.util.*;
entrada de enumeración pública {
NÍQUEL(5), DIME(10), TRIMESTRE(25), DÓLAR(100),PASTA DE DIENTES(200), CHIPS(75), REFRESCO(100), JABÓN(50),ABORT_TRANSACTION {
public int cantidad() { // No permitir
lanzar nueva RuntimeException("ABORT.amount()");
}
},
STOP { // Esta debe ser la última instancia.
public int cantidad() { // No permitir
lanzar nueva RuntimeException ("SHUT_DOWN.amount()");
}
};
valor int; // En centavos
Entrada (valor int) { this.value = valor }
Aporte() {}
int cantidad() { valor de retorno }; // En centavos
rand aleatorio estático = nuevo aleatorio (47);
entrada estática pública selección aleatoria() {
// No incluye STOP:
valores de retorno()[rand.nextInt(valores().longitud - 1)];
}
} ///:~
VendingMachine se usa para responder a la entrada Primero, clasifica la entrada mediante la enumeración de categorías y luego usa la declaración de cambio:
Copie el código de código de la siguiente manera:
//: enumerado/VendingMachine.java
// {Argumentos: VendingMachineInput.txt}
paquete enumerado;
importar java.util.*;
importar net.mindview.util.*;
importar estática enumerada.Input.*;
importar estática net.mindview.util.Print.*;
enumeración Categoría {
DINERO(NICKEL, DIME, TRIMESTRE, DÓLAR),ITEM_SELECTION(PASTA DE DIENTES, CHIPS, SODA, JABÓN),QUIT_TRANSACTION(ABORT_TRANSACTION),SHUT_DOWN(STOP);
valores privados de entrada [];
Categoría(Entrada... tipos) { valores = tipos }
categorías privadas estáticas de EnumMap<Input,Category> = new EnumMap<Input,Category>(Input.class);
estático {
para (Categoría c: Categoría.class.getEnumConstants())
para (tipo de entrada: c.valores)
categorías.put(tipo, c);
}
Categoría estática pública categorizar (entrada de entrada) {
devolver categorías.get(entrada);
}
}
Máquina expendedora de clase pública {
Estado estático privado estado = Estado.RESTING;
cantidad int estática privada = 0;
Selección de entrada estática privada = nula;
enum StateDuration {TRANSIENT} //Etiquetado de enum
estado de enumeración {
DESCANSANDO {
anular siguiente (entrada de entrada) {
cambiar(Categoría.categorizar(entrada)) {
caso DINERO:
monto += entrada.monto();
estado = AGREGAR_DINERO;
romper;
caso APAGADO:
estado = TERMINAL;
por defecto:
}
}
},
AGREGANDO_DINERO {
anular siguiente (entrada de entrada) {
cambiar(Categoría.categorizar(entrada)) {
caso DINERO:
monto += entrada.monto();
romper;
caso ITEM_SELECTION:
selección = entrada;
if(cantidad <selección.cantidad())
print("Dinero insuficiente para " + selección);
demás estado = DISPENSACIÓN;
romper;
caso QUIT_TRANSACTION:
estado = DAR_CAMBIO;
romper;
caso APAGADO:
estado = TERMINAL;
por defecto:
}
}
},
DISPENSACIÓN(EstadoDuración.TRANSIENTO) {
anular siguiente() {
print("aquí está su " + selección);
monto -= selección.monto();
estado = DAR_CAMBIO;
}
},
DANDO_CAMBIO(DuraciónEstado.TRANSIENT) {
anular siguiente() {
si(monto > 0) {
print("Su cambio: " + monto);
cantidad = 0;
}
estado = DESCANSO;
}
},
TERMINAL { salida nula() { print("Detenido");
booleano privado isTransient = false;
Estado() {}
Estado(StateDuration trans) { isTransient = true }
anular siguiente (entrada de entrada) {
throw new RuntimeException("Solo llame a " + "siguiente (entrada de entrada) para estados no transitorios");
}
anular siguiente() {
throw new RuntimeException ("Solo llame a next() para " + "estados StateDuration.TRANSIENT");
}
salida nula() { imprimir(cantidad }
}
ejecución vacía estática (Generador <entrada> gen) {
mientras(estado!= Estado.TERMINAL) {
estado.siguiente(gen.siguiente());
mientras (estado.isTransient)
estado.siguiente();
estado.salida();
}
}
público estático vacío principal (String [] argumentos) {
Generador<Input> gen = nuevo RandomInputGenerator();
si(args. longitud == 1)
gen = nuevo FileInputGenerator(args[0]);
ejecutar(gen);
}
}
// Para una comprobación básica de cordura:
clase RandomInputGenerator implementa Generador<Entrada> {
Entrada pública siguiente() { return Entrada.Selección aleatoria() }
}
// Crea entradas a partir de un archivo de cadenas separadas por ';':
clase FileInputGenerator implementa Generador<Entrada> {
entrada privada Iterador<Cadena>;
public FileInputGenerator (nombre de archivo de cadena) {
entrada = nuevo archivo de texto (nombre de archivo, ";"). iterador();
}
entrada pública siguiente() {
si(!entrada.hasNext())
devolver nulo;
return Enum.valueOf(Input.class, input.next().trim());
}
} /* Producción:
aqui estan tus CHIPS
aquí está tu pasta de dientes
Tu cambio: 35
Dinero insuficiente para SODA
Dinero insuficiente para SODA
Tu cambio: 75
Detenido
*///:~
Aquí están los datos de prueba utilizados para generar el resultado anterior:
Copie el código de código de la siguiente manera:
CUARTO; CUARTO; CUARTO;
DÓLAR; DÓLAR;
CUARTO; DIME; ABORTAR_TRANSACCIÓN;
CUARTO; DIME; REFRESCO;
CUARTO; DIME; NÍQUEL; REFRESCO;
ABORTAR_TRANSACCIÓN;
DETENER;
///:~
Desempaquetado múltiple Cuando se trata de interacciones entre múltiples tipos, es probable que el código se vuelva confuso, como Number.plush(Number), Number.mutiply(Number), etc. Number es solo una clase base de la familia, por lo que cuando llamas Cuando a.plus (b), no conoce el tipo de a ni el tipo de b, entonces, ¿cómo garantizar que la interacción entre ellos sea correcta? Java solo puede realizar un desempaquetado único, es decir, si se realizan una o más operaciones de múltiples tipos desconocidos, Java solo puede realizar un mecanismo de enlace dinámico en uno de los tipos, lo que no puede resolver el problema del que hablamos anteriormente. para escribir manualmente el código de enlace dinámico.
La solución es utilizar enlaces múltiples. El polimorfismo solo puede ocurrir al llamar a un método, por lo que si necesita descomprimirlo varias veces, debe llamar a varios métodos. Con desenvolvimiento múltiple, debe tener un método virtual que llame al método de cada tipo para desenvolver. El siguiente ejemplo es un ejemplo de piedra, papel y tijera:
Copie el código de código de la siguiente manera:
//: enumerado/Resultado.java
paquete enumerado;
resultado de enumeración pública {GANAR, PERDER, EMPATE} ///:~
//: enumerado/RoShamBo1.java
// Demostración de despacho múltiple.
paquete enumerado;
importar java.util.*;
importar estática enumerada.Resultado.*;
elemento de interfaz {
Resultado competir(Ítem it);
Evaluación de resultados (Documento p);
Evaluación de resultados (Tijeras);
Evaluación de resultados (Rock r);
}
clase Papel implementa Artículo {
Resultado público competir (Artículo) {return it.eval(this);
evaluación de resultados públicos (Papel p) { return DRAW }
evaluación de resultados públicos (tijeras) {return WIN;
evaluación de resultados públicos (Rock r) {return LOSE;
cadena pública toString() {return "Papel";
}
clase Tijeras implementa Artículo {
Resultado público competir (Artículo) {return it.eval(this);
evaluación de resultados públicos (documento p) {return LOSE;
evaluación de resultados públicos (tijeras) { return DRAW }
evaluación de resultados públicos (Rock r) { return WIN }
public String toString() { return "Tijeras" }
}
clase Rock implementa el artículo {
Resultado público competir (Artículo) {return it.eval(this);
evaluación de resultados públicos (documento p) {return WIN;
evaluación de resultados públicos (Tijeras s) {return LOSE;
evaluación de resultados públicos (Rock r) { return DRAW }
cadena pública toString() {return "Roca";
}
clase pública RoShamBo1 {
estático final int TAMAÑO = 20;
rand aleatorio estático privado = nuevo aleatorio (47);
Artículo estático público nuevoItem() {
cambiar(rand.nextInt(3)) {
por defecto:
caso 0: devolver nuevas tijeras();
caso 1: devolver papel nuevo();
caso 2: devolver nueva Roca();
}
}
coincidencia nula estática pública (elemento a, elemento b) {
System.out.println(a + "vs. " + b + ": " + a.compete(b));
}
público estático vacío principal (String [] argumentos) {
para(int i = 0; i < TAMAÑO; i++)
partido(nuevoItem(), nuevoItem());
}
} /* Producción:
Rock vs Rock: SORTEO
Papel versus piedra: GANAR
Papel versus piedra: GANAR
Papel versus piedra: GANAR
Tijeras vs. Papel: GANAR
Tijera vs Tijera: SORTEO
Tijeras vs. Papel: GANAR
Piedra contra papel: PERDER
Papel vs. Papel: SORTEO
Piedra contra papel: PERDER
Papel versus tijeras: PERDER
Papel versus tijeras: PERDER
Piedra contra tijeras: GANAR
Piedra contra papel: PERDER
Papel versus piedra: GANAR
Tijeras vs. Papel: GANAR
Papel versus tijeras: PERDER
Papel versus tijeras: PERDER
Papel versus tijeras: PERDER
Papel versus tijeras: PERDER
*///:~
Usamos muchos métodos para lograr un desempaquetado múltiple, pero lo que obtuvimos fue una buena estructura de código. El mayor problema al utilizar una solución de enumeración para implementar el código anterior es que la instancia de enumeración no es un tipo, por lo que la instancia de enumeración no se puede utilizar como tipo de parámetro. Pero todavía podemos tener otras formas de sortear este obstáculo. Una forma es utilizar un constructor para inicializar cada tipo de enumeración y luego organizar la salida en una tabla de búsqueda:
Copie el código de código de la siguiente manera:
//: enumerado/RoShamBo2.java
// Cambiando una enumeración por otra.
paquete enumerado;
importar estática enumerada.Resultado.*;
enumeración pública RoShamBo2 implementa Competidor<RoShamBo2> {
PAPEL(EMPATE, PERDER, GANAR),TIJERAS(GANAR, EMPATE, PERDER),ROCA(PERDER, GANAR, EMPATE);
Resultado privado vPAPEL, vTIJERAS, vROCK;
RoShamBo2(Documento de resultados,Tijeras de resultados,Roca de resultados) {
this.vPAPER = papel;
this.vscissors = sicisss;
this.vrock = rock;
}
Public Resulte Compete (Roshambo2 It) {
cambiar (it) {
por defecto:
Documento de casos: return vpaper;
tijeras de casos: return vScissors;
Case Rock: return vrock;
}
}
público estático vacío principal (String [] argumentos) {
Roshambo.play (Roshambo2.class, 20);
}
} /* Producción:
Rock vs. Rock: Draw
Tijeras vs. rock: perder
Tijeras vs. rock: perder
Tipos enumerados 753
Tijeras vs. rock: perder
Documento vs. tijeras: perder
Paper vs. Paper: Draw
Documento vs. tijeras: perder
Rock vs. Scissors: Win
Tijeras vs. tijeras: dibujar
Rock vs. Scissors: Win
Tijeras vs. papel: ganar
Tijeras vs. papel: ganar
Rock vs. Paper: perder
Rock vs. Scissors: Win
Tijeras vs. rock: perder
Documento vs. tijeras: perder
Tijeras vs. papel: ganar
Tijeras vs. papel: ganar
Tijeras vs. papel: ganar
Tijeras vs. papel: ganar
*///:~
Copie el código de código de la siguiente manera:
//: enumerado/competidor.java
// Cambiar un enum en otro.
paquete enumerado;
El competidor de la interfaz pública <t extiende el competidor <t>> {
Resultado competir (competidor t);
} ///: ~
Copie el código de código de la siguiente manera:
//: enumerado/Roshambo.java
// Herramientas comunes para ejemplos de Roshambo.
paquete enumerado;
importar net.mindview.util.*;
clase pública Roshambo {
public static <t extiende la competencia <T>> Void Match (t a, t b) {
System.out.println (A + "vs." + B + ":" + A.Compete (b));
}
public static <t extiende enum <t> y competidor <t>> Void Play (class <t> rsbclass, int size) {
para (int i = 0; i <size; i ++)
Match (enums.random (rsbclass), enums.random (rsbclass));
}
} ///: ~
Debido a que la formulación de métodos estáticos puede proporcionar diferentes métodos para cada tipo de enumeración, parece ser una buena solución para lograr múltiples desempaquetamiento, pero aún enfrentamos el problema de que la instancia de enumeración no es un tipo, por lo que todo lo que podemos hacer es agregar una instrucción Switch :
Copie el código de código de la siguiente manera:
//: enumerado/Roshambo3.java
// Uso de métodos específicos constantes.
paquete enumerado;
importar estática enumerada.outcome.*;
public enum Roshambo3 implementa el competidor <Roshambo3> {
PAPEL {
Public Resulte Compete (Roshambo3 It) {
cambiar (it) {
predeterminado: // para colocar el compilador
Documento de caso: Draw de retorno;
CASO DE CASO: RETURN PERDE;
Case Rock: Victoria de regreso;
}
}
},
TIJERAS {
Public Resulte Compete (Roshambo3 It) {
cambiar (it) {
por defecto:
Documento de casos: retorno de victoria;
CASO DE CASO: Draw de retorno;
Case Rock: Return se pierde;
}
}
},
ROCA {
Public Resulte Compete (Roshambo3 It) {
cambiar (it) {
por defecto:
Documento de casos: devolución de pérdida;
CASO DE CASO: VITRA DE RETURN;
Case Rock: Draw de retorno;
}
}
};
Resumen de resumen público Compite (Roshambo3 IT);
público estático vacío principal (String [] argumentos) {
Roshambo.play (Roshambo3.class, 20);
}
}/ * La misma salida que Roshambo2.Java * ///: ~
El siguiente código es un método de implementación más conciso:
Copie el código de código de la siguiente manera:
//: enumerado/Roshambo4.java
paquete enumerado;
public enum Roshambo4 implementa el competidor <Roshambo4> {
ROCA {
Resultado público Compite (oponente de Roshambo4) {
return competir (tijeras, oponente);
}
},
TIJERAS {
Resultado público Compite (oponente de Roshambo4) {
return competir (papel, oponente);
}
},
PAPEL {
Resultado público Compite (oponente de Roshambo4) {
regreso competir (rock, oponente);
}
};
Resultado Compete (Roshambo4 perdedor, oponente de Roshambo4) {
return ((opponente == this)? Result.Draw: ((opponente == perdedor)? resultados.win: dupive.lose));
}
público estático vacío principal (String [] argumentos) {
Roshambo.play (Roshambo4.class, 20);
}
}/ * La misma salida que Roshambo2.Java * ///: ~
La clase enummap parece ser una buena manera de implementar un desempaquetado múltiple:
Copie el código de código de la siguiente manera:
//: Enumerado/Roshambo5.Java
// envío múltiple usando una enumma de enummaps.
paquete enumerado;
importar java.util.*;
importar estática enumerada.outcome.*;
Enum Roshambo5 implementa el competidor <Roshambo5> {
Papel, tijeras, roca;
Enummap estático <Roshambo5, enummap <Roshambo5, Resultado >> table = new Enummap <Roshambo5, enummap <Roshambo5, Resultado >> (Roshambo5.class);
estático {
para (Roshambo5 it: Roshambo5.Values ())
table.put (IT, nuevo enummap <Roshambo5, Resultado> (Roshambo5.class));
initrow (papel, sortear, perder, ganar);
initrow (tijeras, ganar, dibujar, perder);
initrow (rock, perder, ganar, dibujar);
}
static void initrow (Roshambo5 it, resultado vaper, resultados vScissors, resultado vrock) {
Enummap <Roshambo5, resultado> row = Roshambo5.table.get (it);
Row.put (Roshambo5.paper, VPaper);
Row.put (Roshambo5.scissors, VSCISSORS);
Row.put (Roshambo5.Rock, Vrock);
}
Public Resulte Compete (Roshambo5 It) {
return table.get (this) .get (it);
}
público estático vacío principal (String [] argumentos) {
Roshambo.play (Roshambo5.Class, 20);
}
}/ * La misma salida que Roshambo2.Java * ///: ~
También podemos usar la característica de las instancias de enumeración con valores fijos para usar datos para el método de implementación más simple.
Copie el código de código de la siguiente manera:
//: enumerado/Roshambo6.java
// enums usando "tablas" en lugar de envío múltiple.
paquete enumerado;
importar estática enumerada.outcome.*;
Enum Roshambo6 implementa el competidor <Roshambo6> {
Papel, tijeras, roca;
Resultado estático privado [] [] table = {
{Dibujar, perder, ganar}, // papel
{Ganar, dibujar, perder}, // tijeras
{Perder, ganar, dibujar}, // rock
};
Resultado público Compite (Roshambo6 Other) {
Tabla de retorno [this.ordinal ()] [other.ordinal ()];
}
público estático vacío principal (String [] argumentos) {
Roshambo.play (Roshambo6.class, 20);
}
} ///: ~