Il existe une méthode de valeurs dans l'énumération qui est utilisée pour générer un tableau dans l'ordre défini par l'énumération, qui peut être utilisé pour parcourir. Nos classes d'énumération personnalisées héritent toutes de java.lang.Enum et ont les fonctions suivantes dans les exemples :
Copiez le code comme suit :
// : énuméré/EnumClass.java
// Capacités de la classe Enum
importer un net.mindview.util.Print.* statique;
enum Arbustes { SOL, RAMPANT, SUSPENDU }
classe publique EnumClass {
public static void main (String[] arguments) {
pour (Arbustes s : Arbustes.values()) {
print(s + " ordinal : " + s.ordinal());
printnb(s.compareTo(Shrubbery.CRAWLING) + " ");
printnb(s.equals(Shrubbery.CRAWLING) + " ");
print(s == Arbustes.CRAWLING);
print(s.getDeclaringClass());
print(s.name());
imprimer("----------------------");
}
// Produit une valeur enum à partir d'un nom de chaîne :
for(String s : "SUSPENDU CRAWLING GROUND".split(" ")) {
Arbuste arbustif = Enum.valueOf(Shrubbery.class, s);
imprimer(arbuste);
}
}
} /* Sortir:
ordinal TERRE : 0
-1 faux faux
classe Arbuste
Joshua Bloch a été extrêmement utile dans l'élaboration de ce chapitre.
SOL
-----------------------
Ordinaire d'exploration : 1
vrai vrai
classe Arbuste
RAMPANT
-----------------------
Ordinaire SUSPENDU : 2
faux faux
classe Arbuste
SUSPENDU
-----------------------
SUSPENDU
RAMPANT
SOL
*///:~
Nous pouvons également utiliser des références d'énumération statique :
Copiez le code comme suit :
// : énuméré/épicé.java
paquet énuméré ;
public enum Piquant {PAS, DOUX, MOYEN, CHAUD, FLAMING} ///:~
// : énuméré/Burrito.java
paquet énuméré ;
import static enumerated.Spiciness.* ;
Burrito de classe publique {
Degré de piquant ;
public Burrito (degré épicé) { this.degree = degré;}
public String toString() { return "Burrito est" + degré ;}
public static void main (String[] arguments) {
System.out.println (nouveau Burrito (PAS));
System.out.println(nouveau Burrito(MEDIUM));
System.out.println (nouveau Burrito (CHAUD));
}
} /* Sortir:
Le burrito n'est PAS
Le burrito est MOYEN
Le burrito est CHAUD
*///:~
En plus d'ajouter des méthodes à une énumération, qui ne peuvent pas être héritées, l'énumération peut être traitée comme une classe générale, ce qui signifie que vous pouvez ajouter des méthodes à l'énumération, et vous pouvez également définir la méthode principale dans l'énumération :
Copiez le code comme suit :
// : énuméré/OzWitch.java
// Les sorcières au pays d'Oz.
importer un net.mindview.util.Print.* statique;
énumération publique OzWitch {
// Les instances doivent être définies en premier, avant les méthodes :
OUEST("Miss Gulch, alias la Méchante Sorcière de l'Ouest"),NORD("Glinda, la Bonne Sorcière du Nord"),EST("Méchante Sorcière de l'Est, porteuse du Rubis " + "Pantoufles, écrasées par La maison de Dorothy"),SUD("Bon par déduction, mais manquant");
Description de la chaîne privée ;
// Le constructeur doit être un package ou un accès privé :
privé OzWitch (description de la chaîne) {
this.description = description ;
}
public String getDescription() { return description }
public static void main (String[] arguments) {
pour (sorcière OzWitch : OzWitch.values())
print(sorcière + ": " + sorcière.getDescription());
}
} /* Sortir:
OUEST : Miss Gulch, alias la méchante sorcière de l'Ouest
NORD : Glinda, la bonne sorcière du Nord
EST : Méchante Sorcière de l'Est, porteuse des Chaussons Rubis, écrasée par la maison de Dorothy
SUD : Bon par déduction, mais manquant
*///:~
Copiez le code comme suit :
// : énuméré/SpaceShip.java
énumération publique SpaceShip {
SCOUT, CARGO, TRANSPORT, CRUISER, CUIRASSÉ, NAVIRE-MÈRE ;
chaîne publique toString() {
ID de chaîne = nom();
Chaîne inférieure = id.substring(1).toLowerCase();
return id.charAt(0) + inférieur ;
}
public static void main (String[] arguments) {
pour (SpaceShip s : valeurs ()) {
System.out.println(s);
}
}
} /* Sortir:
Scout
Cargaison
Transport
Croiseur
Navire de guerre
Vaisseau mère
*///:~
Énumérations dans les instructions switch Les énumérations jouent généralement un rôle important dans les instructions switch. Habituellement, les instructions switch ne fonctionnent que sur des valeurs entières, mais il existe un ordre intégré des entiers dans les énumérations, de sorte que l'ordre des instances peut être déterminé par une méthode obtenue. les énumérations peuvent donc être utilisées dans les instructions switch :
Copiez le code comme suit :
// : énuméré/TrafficLight.java
// Énumérations dans les instructions switch.
importer un net.mindview.util.Print.* statique;
// Définir un type d'énumération :
enum Signal {VERT, JAUNE, ROUGE, }
classe publique TrafficLight {
Couleur du signal = Signal.RED ;
changement de vide public() {
changer (couleur) {
// Notez que vous n'êtes pas obligé de dire Signal.RED
// dans l'instruction case :
cas ROUGE : couleur = Signal.GREEN ;
casser;
cas VERT : couleur = Signal.YELLOW ;
casser;
cas JAUNE : couleur = Signal.RED ;
casser;
}
}
chaîne publique toString() {
return "Le feu est " + couleur ;
}
public static void main (String[] arguments) {
TrafficLight t = nouveau TrafficLight();
pour(int je = 0; je < 7; je++) {
imprimer(t);
t.change();
}
}
} /* Sortir:
Le feu est ROUGE
Le feu est VERT
Le feu de circulation est JAUNE
Le feu est ROUGE
Le feu est VERT
Le feu de circulation est JAUNE
Le feu est ROUGE
*///:~
Le secret des valeurs() Bien que nous ayons utilisé la méthode des valeurs auparavant, si nous regardons Enum, nous ne trouvons pas la méthode des valeurs. Alors, y a-t-il d'autres méthodes cachées ? Nous pouvons le vérifier avec un simple code de réflexion :
Copiez le code comme suit :
// : énuméré/Reflection.java
// Analyse des énumérations à l'aide de la réflexion.
importer java.lang.reflect.* ;
importer java.util.* ;
importer net.mindview.util.* ;
importer un net.mindview.util.Print.* statique;
enum Explorer { ICI, LÀ }
Réflexion de classe publique {
public static Set<String> analyse(Class<?> enumClass) {
print("----- Analyse " + enumClass + " -----");
print("Interfaces :");
pour (Type t : enumClass.getGenericInterfaces())
imprimer(t);
print("Base : " + enumClass.getSuperclass());
print("Méthodes : ");
Méthodes Set<String> = new TreeSet<String>();
pour (Méthode m : enumClass.getMethods())
méthodes.add(m.getName());
print(méthodes);
méthodes de retour ;
}
public static void main (String[] arguments) {
Set<String> exploreMethods = analyse(Explore.class);
Set<String> enumMethods = analyse(Enum.class);
print("Explore.containsAll(Enum)? " +
exploreMethods.containsAll(enumMethods));
printnb("Explore.removeAll(Enum): ");
exploreMethods.removeAll(enumMethods);
print(exploreMethods);
// Décompilez le code de l'énumération :
OSExecute.command("javap Explorer");
}
} /* Sortir:
----- Classe d'analyse Explorer -----
Interfaces :
Base : classe java.lang.Enum
Méthodes :
[compareTo, égal à, getClass, getDeclaringClass, hashCode, nom, notifier, notifierAll, ordinal, toString, valueOf, valeurs, attendre]
----- Analyse de la classe java.lang.Enum -----
Interfaces :
java.lang.Comparable<E>
interface java.io.Sérialisable
Base : classe java.lang.Object
Méthodes :
[compareTo, equals, getClass, getDeclaringClass, hashCode, name, notify, notifyAll, ordinal, toString, valueOf, wait]
Explore.containsAll(Enum) ?
Explore.removeAll (Enum): [valeurs]
Compilé à partir de "Reflection.java"
la classe finale Explore étend java.lang.Enum{
public statique final Explorez ICI ;
public statique final Explorez LÀ ;
valeurs finales publiques statiques Explore[] ();
public static Explorer valueOf (java.lang.String);
statique {} ;
}
*///:~
On peut voir que la méthode des valeurs est ajoutée par le compilateur. La méthode valueOf est également ajoutée par le compilateur lors de la création de l'énumération, mais il existe également une méthode valueOf dans la classe Enum, mais cette méthode a deux paramètres, tandis que la méthode valueOf ajoutée par le compilateur n'a qu'un seul paramètre. Les énumérations sont interprétées comme finales par le compilateur, elles ne peuvent donc pas être héritées. Étant donné que la méthode des valeurs est une méthode statique ajoutée par le compilateur, si vous convertissez l'énumération en Enum, la méthode des valeurs ne sera pas disponible, mais il existe une méthode getEnumConstants dans Class, donc bien que la méthode des valeurs soit non disponible dans Enum , mais vous pouvez toujours obtenir l'instance d'énumération via l'objet Class :
Copiez le code comme suit :
// : énuméré/UpcastEnum.java
// Pas de méthode Values() si vous convertissez une énumération
enum Rechercher { HITHER, YON }
classe publique UpcastEnum {
public static void main (String[] arguments) {
Search[] vals = Search.values();
Enum e = Search.HITHER; // Upcast
// e.values(); // Aucune valeur() dans Enum
for(Enum en : e.getClass().getEnumConstants())
System.out.println(fr);
}
} /* Sortir:
ICI
YON
*///:~
Implémentation sans héritage Étant donné que les types d'énumération que nous définissons héritent tous de java.lang.Enum et que Java ne prend pas en charge l'héritage multiple, les énumérations ne sont donc pas créées par héritage, mais les énumérations peuvent être créées en héritant d'une ou plusieurs interfaces :
Copiez le code comme suit :
// : énuméré/cartoons/EnumImplementation.java
// Une énumération peut implémenter une interface
paquet énuméré.cartoons;
importer java.util.* ;
importer net.mindview.util.* ;
enum CartoonCharacter implémente Generator<CartoonCharacter> {
SLAPPY, SPANKY, PUNCHY, SILLY, BOUNCY, NUTTY, BOB ;
Rand aléatoire privé = nouveau Random (47);
public CartoonCharacter suivant() {
valeurs de retour()[rand.nextInt(values().length)];
}
}
classe publique EnumImplementation {
public static <T> void printNext(Generator<T> rg) {
System.out.print(rg.next() + ", ");
}
public static void main (String[] arguments) {
// Choisissez n'importe quelle instance :
CartoonCharacter cc = CartoonCharacter.BOB;
pour(int je = 0; je < 10; je++)
printNext(cc);
}
} /* Sortir:
BOB, PUNCHY, BOB, SPANKY, NUTTY, PUNCHY, SLAPPY, NUTTY, NUTTY, SLAPPY,
*///:~
Sélection aléatoire Dans plusieurs de nos exemples ultérieurs, nous sélectionnerons aléatoirement des objets à partir d'instances d'énumération. Nous créons une classe publique pour implémenter ceci :
Copiez le code comme suit :
// : net/mindview/util/Enums.java
paquet net.mindview.util;
importer java.util.* ;
Énumérations de classe publique {
rand aléatoire statique privé = new Random (47);
public static <T extends Enum<T>> T random(Class<T> ec) {
return random(ec.getEnumConstants());
}
public static <T> T aléatoire (valeurs T[]) {
valeurs de retour[rand.nextInt(values.length)];
}
} ///:~
Copiez le code comme suit :
// : énuméré/RandomTest.java
importer net.mindview.util.* ;
enum Activité { ASSISE, MENTIQUÉ, DEBOUT, SAUTER, COURIR, ÉVITER, SAUTER, TOMBER, VOLER }
classe publique RandomTest {
public static void main (String[] arguments) {
pour(int je = 0; je < 20; je++)
System.out.print(Enums.random(Activity.class) + " ");
}
} /* Sortir:
DEBOUT VOLER COURIR DEBOUT COURIR DEBOUT ALLONGÉ ÉVITER ASSIS COURIR SAUTER SAUTER COURIR DEBOUT ALLONGÉ TOMBER COURIR VOLER MENTIR
*///:~
L'utilisation d'interfaces pour organiser les énumérations ne peut pas être héritée, ce qui nous cause parfois des désagréments, car parfois nous voulons augmenter le nombre d'énumérations par héritage, et parfois nous devons regrouper les énumérations. Pour ces derniers, nous pouvons définir des énumérations groupées au sein de l'interface, puis créer l'énumération en héritant de cette interface. Comme suit, nous avons différentes catégories d'aliments qui doivent être créées sous forme d'énumérations, mais nous devons définir chaque catégorie comme types. de la nourriture sont les suivantes :
Copiez le code comme suit :
// : énuméré/menu/Food.java
// Sous-catégorisation des énumérations dans les interfaces.
paquet énuméré.menu;
interface publique Nourriture {enum Appetizer implémente Nourriture {SALAD, SOUP, SPRING_ROLLS;}
enum MainCourse implémente Food {LASAGNE, BURRITO, PAD_THAI, LENTILS, HUMMOUS, VINDALOO;}
enum Dessert met en œuvre la nourriture {TIRAMISU, GELATO, BLACK_FOREST_CAKE,FRUIT, CREME_CARAMEL;}
enum Coffee met en œuvre la nourriture {BLACK_COFFEE, DECAF_COFFEE, ESPRESSO,LATTE, CAPPUCCINO, TEA, HERB_TEA;}
} ///:~
Étant donné que chaque énumération est définie comme une implémentation d’une interface, chaque énumération est de type Food, comme suit :
Copiez le code comme suit :
// : énuméré/menu/TypeOfFood.java
paquet énuméré.menu;
importer un enumerated.menu.Food.* statique;
classe publique TypeOfFood {
public static void main (String[] arguments) {
Nourriture nourriture = Apéritif.SALADE ;
nourriture = MainCourse.LASAGNE;
nourriture = Dessert.GELATO ;
nourriture = Café.CAPPUCCINO ;
}
} ///:~
Mais les interfaces ne peuvent pas fonctionner sur plusieurs types comme les énumérations, donc si vous avez besoin d'une énumération d'énumérations, vous pouvez encapsuler une instance de chaque type d'énumération dans une énumération :
Copiez le code comme suit :
// : énuméré/menu/Cours.java
paquet énuméré.menu;
importer net.mindview.util.* ;
Cours public enum {
APPETIZER (Food.Appetizer.class), MAINCOURSE (Food.MainCourse.class), DESSERT (Food.Dessert.class), CAFÉ (Food.Coffee.class);
valeurs Food[] privées ;
Cours privé (Classe <? extends Food> type) {
valeurs = kind.getEnumConstants();
}
nourriture publique randomSelection() {
return Enums.random (valeurs);
}
} ///:~
Chaque énumération utilise l'objet Class comme paramètre de constructeur correspondant. Nous pouvons utiliser getEnumConstants à partir de ce paramètre pour obtenir l'instance d'énumération. Cette instance peut être utilisée dans la méthode randomSelection pour générer des repas aléatoires :
Copiez le code comme suit :
// : énuméré/menu/Repas.java
paquet énuméré.menu;
Repas en classe publique {
public static void main (String[] arguments) {
pour(int je = 0; je < 5; je++) {
for(Cours cours : Course.values()) {
Nourriture nourriture = course.randomSelection();
System.out.println(nourriture);
}
System.out.println("---");
}
}
} /* Sortir:
SPRING_ROLLS
VINDALOO
FRUIT
DECAF_CAFÉ
---
SOUPE
VINDALOO
FRUIT
THÉ
---
SALADE
BURRITOS
FRUIT
THÉ
---
SALADE
BURRITOS
CREME_CARAMEL
LATTÉ
---
SOUPE
BURRITOS
TIRAMISU
ESPRESSO
---
*///:~
Voici une implémentation plus compacte :
Copiez le code comme suit :
// : énuméré/SecurityCategory.java
// Sous-catégorisation plus succincte des énumérations.
importer net.mindview.util.* ;
enum Catégorie de sécurité {
STOCK(Security.Stock.class), BOND(Security.Bond.class);
Valeurs de sécurité[] ;
SecurityCategory(Class<? extends Security> genre) {
valeurs = kind.getEnumConstants();
}
sécurité de l'interface {
enum Stock implémente la sécurité {SHORT, LONG, MARGIN}
enum Bond implémente la sécurité { MUNICIPAL, JUNK }
}
sécurité publique randomSelection() {
return Enums.random (valeurs);
}
public static void main (String[] arguments) {
pour(int je = 0; je < 10; je++) {
Catégorie SecurityCategory = Enums.random (SecurityCategory.class);
System.out.println(catégorie + ": " +
catégorie.randomSelection());
}
}
} /* Sortir:
OBLIGATION : MUNICIPALE
OBLIGATION : MUNICIPALE
STOCK : MARGE
STOCK : MARGE
LIEN : INJUSTÈ
CROCHET : COURT
CROSSE : LONGUE
CROSSE : LONGUE
OBLIGATION : MUNICIPALE
LIEN : INJUSTÈ
*///:~
Copiez le code comme suit :
// : énuméré/menu/Meal2.java
paquet énuméré.menu;
importer net.mindview.util.* ;
énumération publique Repas2 {
APPETIZER (Food.Appetizer.class), MAINCOURSE (Food.MainCourse.class), DESSERT (Food.Dessert.class), CAFÉ (Food.Coffee.class);
valeurs Food[] privées ;
Repas privé2(Class<? extends Food> genre) {
valeurs = kind.getEnumConstants();
}
interface publique Alimentation {
enum Apéritif implémente Food {SALAD, SOUP, SPRING_ROLLS;}
enum MainCourse implémente Food {LASAGNE, BURRITO, PAD_THAI, LENTILS, HUMMOUS, VINDALOO;}
enum Dessert met en œuvre la nourriture {TIRAMISU, GELATO, BLACK_FOREST_CAKE,FRUIT, CREME_CARAMEL;}
enum Coffee met en œuvre la nourriture {BLACK_COFFEE, DECAF_COFFEE, ESPRESSO,LATTE, CAPPUCCINO, TEA, HERB_TEA;}
}
nourriture publique randomSelection() {
return Enums.random (valeurs);
}
public static void main (String[] arguments) {
pour(int je = 0; je < 5; je++) {
pour (repas Meal2 : Meal2.values()) {
Nourriture nourriture = repas.randomSelection();
System.out.println(nourriture);
}
System.out.println("---");
}
}
} /* Même résultat que Meal.java *///:~
Utiliser EnumSet au lieu des indicateurs EnumSet a été ajouté dans Java SE5 pour combiner des énumérations et des ensembles afin de remplacer les indicateurs de bits basés sur des entiers. Les indicateurs de bits sont généralement utilisés pour indiquer le changement d'un certain type d'information, mais dans le code, les bits sont exploités plutôt que des concepts significatifs, ils ne sont donc pas faciles à comprendre. EnumSet est plus rapide que les indicateurs de bits. Il utilise long en interne pour représenter un vecteur de bits, et vous pouvez ensuite utiliser un langage plus conceptuel pour représenter le changement d'un certain bit sans vous soucier de l'efficacité. Les éléments dans EnumSet doivent provenir de la même énumération. Ce qui suit définit une énumération de la position d'alarme :
Copiez le code comme suit :
// : énuméré/AlarmPoints.java
paquet énuméré ;
public enum AlarmPoints {ESCALIER1, ESCALIER2, LOBBY, BUREAU1, BUREAU2, BUREAU3, BUREAU4, SALLE DE BAINS, UTILITAIRE, CUISINE} ///:~
Utilisez ensuite la classe EnumSet pour suivre l'état de l'alarme :
Copiez le code comme suit :
// : énuméré/EnumSets.java
// Opérations sur EnumSets
paquet énuméré ;
importer java.util.* ;
importer des énumérations statiques.AlarmPoints.* ;
importer un net.mindview.util.Print.* statique;
classe publique EnumSets {
public static void main (String[] arguments) {
EnumSet<AlarmPoints> points = EnumSet.noneOf(AlarmPoints.class); // Ensemble vide
points.add(SALLE DE BAINS);
imprimer(points);
points.addAll(EnumSet.of(ESCALIER1, ESCALIER2, CUISINE));
imprimer(points);
points = EnumSet.allOf(AlarmPoints.class);
points.removeAll(EnumSet.of(ESCALIER1, ESCALIER2, CUISINE));
imprimer(points);
points.removeAll(EnumSet.range(OFFICE1, OFFICE4));
imprimer(points);
points = EnumSet.complementOf(points);
imprimer(points);
}
} /* Sortir:
[SALLE DE BAIN]
[ESCALIER1, ESCALIER2, SALLE DE BAINS, CUISINE]
[HALL, BUREAU1, BUREAU2, BUREAU3, BUREAU4, SALLE DE BAINS, UTILITAIRE]
[HALL, SALLE DE BAINS, UTILITAIRE]
[ESCALIER1, ESCALIER2, BUREAU1, BUREAU2, BUREAU3, BUREAU4, CUISINE]
*///:~
EnumSet est construit sur un type long et comporte 64 bits, alors que se passe-t-il si notre type d'énumération dépasse ce nombre ?
Copiez le code comme suit :
// : énuméré/BigEnumSet.java
importer java.util.* ;
classe publique BigEnumSet {
enum Grand { 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}
public static void main (String[] arguments) {
EnumSet<Big> bigEnumSet = EnumSet.allOf(Big.class);
System.out.println(bigEnumSet);
}
} /* Sortir:
[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]
*///:~
Nous pouvons voir que le programme fonctionne normalement, il est donc très probable qu'un type long ait été ajouté en interne pour aider à s'adapter au type d'énumération utilisant EnumMap.
EnumMap est un type spécial de Map. La valeur de sa clé ne peut être que le type dans la même énumération. Pour cette raison, EnumMap peut être implémenté en interne via un tableau, ce qui est très efficace.
Copiez le code comme suit :
// : énuméré/EnumMaps.java
// Bases d'EnumMaps.
paquet énuméré ;
importer java.util.* ;
importer des énumérations statiques.AlarmPoints.* ;
importer un net.mindview.util.Print.* statique;
commande d'interface {action vide();
classe publique EnumMaps {
public static void main (String[] arguments) {
EnumMap<AlarmPoints,Command> em = new EnumMap<AlarmPoints,Command>(AlarmPoints.class);
em.put(CUISINE, nouvelle Commande() {
public void action() { print("Feu de cuisine !" );
});
em.put(SALLE DE BAINS, nouvelle Commande() {
public void action() { print("Alerte salle de bain !" );
});
for(Map.Entry<AlarmPoints,Command> e : em.entrySet()) {
printnb(e.getKey() + ": ");
e.getValue().action();
}
try { // S'il n'y a aucune valeur pour une clé particulière :
em.get(UTILITY).action();
} catch(Exception e) {
imprimer(e);
}
}
} /* Sortir:
SALLE DE BAINS : Alerte salle de bains !
CUISINE : Feu de cuisine !
java.lang.NullPointerException
*///:~
Méthodes constantes spécifiques Les énumérations Java ont une fonctionnalité très intéressante, c'est-à-dire que différents comportements peuvent être définis pour chaque instance d'énumération. Pour y parvenir, nous définissons une ou plusieurs méthodes abstraites dans le cadre de l'énumération, puis définissons des comportements différents pour chacune. instance d'énumération. Une méthode de définition d'instance d'énumération :
Copiez le code comme suit :
// : énuméré/ConstantSpecificMethod.java
importer java.util.* ;
importer java.text.*;
énumération publique ConstantSpecificMethod {
DATE_TIME {String getInfo() {return DateFormat.getDateInstance().format(new Date());}},
CLASSPATH {String getInfo() {return System.getenv("CLASSPATH");}},
VERSION {String getInfo() {return System.getProperty("java.version");}} ;
chaîne abstraite getInfo();
public static void main (String[] arguments) {
pour (ConstantSpecificMethod csm : valeurs ())
System.out.println(csm.getInfo());
}
} /* (Exécuter pour voir le résultat) *///:~
Le code ci-dessus semble indiquer que chaque élément d'énumération est un élément différent et que tous les éléments héritent de la classe de base ConstantSpecificMethod, mais nous ne pouvons pas vraiment le comprendre de cette façon, car nous ne pouvons pas traiter les éléments d'énumération comme des types :
Copiez le code comme suit :
// : énuméré/NotClasses.java
// {Exec : javap -c LikeClasses}
importer un net.mindview.util.Print.* statique;
enum LikeClasses {WINKEN { void behavior() { print("Behavior1"); BLINKEN { void behavior() { print("Behavior2" } },NOD { void behavior() { print("Behavior3") ; } };
comportement vide abstrait ();
}
classe publique NotClasses {
// void f1 (instance LikeClasses.WINKEN) {} // Non
} /* Sortir:
Compilé à partir de "NotClasses.java"
la classe abstraite LikeClasses étend java.lang.Enum{
public statique final LikeClasses WINKEN ;
public statique final LikeClasses BLINKEN ;
public statique final LikeClasses NOD ;
...
*///:~
Prenons un autre exemple. Il existe un menu de lavage de voiture. Les clients choisissent différents services en fonction de différents menus. Vous pouvez utiliser des méthodes constantes spécifiques pour associer le menu aux services et utiliser EnumSet pour conserver les choix du client, comme suit :
Copiez le code comme suit :
// : énuméré/CarWash.java
importer java.util.* ;
importer un net.mindview.util.Print.* statique;
classe publique CarWash {
public enum Cycle {UNDERBODY {void action() { print("Pulvérisation du dessous de caisse" }});
WHEELWASH {void action() { print("Lavage des roues" }},
PREWASH {void action() { print("Desserrer la saleté" }},
BASIC {void action() { print("Le lavage de base" }},
HOTWAX {void action() { print("Application de cire chaude" }},
RINÇAGE {void action() { print("Rinçage" }},
SOUFFLAGE {void action() { print("Blowdry" }};
action vide abstraite ();
}
EnumSet<Cycle> cycles = EnumSet.of(Cycle.BASIC, Cycle.RINSE);
public void add (Cycle cycle) { cycles.add (cycle });
public void washCar() {
pour(Cycle c : cycles)
c.action();
}
public String toString() { return cycles.toString( );
public static void main (String[] arguments) {
CarWash lavage = nouveau CarWash();
imprimer(laver);
laver.washCar();
// L'ordre d'ajout n'a pas d'importance :
wash.add(Cycle.BLOWDRY);
wash.add(Cycle.BLOWDRY); // Doublons ignorés
laver.ajouter(Cycle.RINSE);
wash.add(Cycle.HOTWAX);
imprimer(laver);
laver.washCar();
}
} /* Sortir:
[BASIQUE, RINÇAGE]
Le lavage de base
Rinçage
[BASIQUE, CIRE CHAUDE, RINÇAGE, SOUFFLAGE]
Le lavage de base
Appliquer de la cire chaude
Rinçage
Sécher au sèche-linge
*///:~
Nous pouvons également remplacer les méthodes constantes spécifiques par défaut au lieu d'utiliser des méthodes abstraites héritées, comme suit :
Copiez le code comme suit :
// : énuméré/OverrideConstantSpecific.java
importer un net.mindview.util.Print.* statique;
énumération publique OverrideConstantSpecific {
ÉCROU, BOULON, RONDELLE {void f() { print("Méthode remplacée" }});
void f() { print("comportement par défaut");
public static void main (String[] arguments) {
for(OverrideConstantSpecific ocs : valeurs()) {
printnb(ocs + ": ");
ocs.f();
}
}
} /* Sortir:
NUT : comportement par défaut
BOLT : comportement par défaut
WASHER : méthode remplacée
*///:~
Parfois, nous souhaitons transmettre des requêtes spécifiques dans la chaîne. Sachant qu'un objet de la chaîne peut gérer la requête peut être facilement réalisé en utilisant des méthodes constantes spécifiques. Voici un exemple de traitement des e-mails :
Copiez le code comme suit :
// : énuméré/PostOffice.java
// Modélisation d'un bureau de poste.
Types énumérés 743
importer java.util.* ;
importer net.mindview.util.* ;
importer un net.mindview.util.Print.* statique;
Courrier de classe {
// Les NON diminuent la probabilité de sélection aléatoire :
enum Livraison générale {OUI, NON1, NO2, NO3, NO4, NO5}
enum Scannabilité {UNSCANNABLE,YES1,YES2,YES3,YES4}
enum Lisibilité {ILLISIBLE, OUI1, OUI2, OUI3, OUI4}
enum Adresse {INCORRECT,OK1,OK2,OK3,OK4,OK5,OK6}
enum ReturnAddress {MANQUANT, OK1, OK2, OK3, OK4, OK5}
Livraison générale livraison générale ;
Numérisation numérisable ;
Lisibilité lisibilité ;
Adresse adresse ;
Adresse de retour Adresse de retour ;
compteur long statique = 0 ;
identifiant long = compteur++ ;
public String toString() { return "Mail" + identifiant }
détails de la chaîne publique() {
return toString() + ", Livraison générale : " + generalDelivery + ", Numérisation de l'adresse : " + numérisabilité + ", Lisibilité de l'adresse : " + lisibilité +
", Adresse Adresse : " + adresse + ", Adresse de retour : " + returnAddress ;
}
//Générer un courrier test :
public static Mail randomMail() {
Courrier m = nouveau courrier ();
m.generalDelivery= Enums.random(GeneralDelivery.class);
m.scannability = Enums.random(Scannability.class);
m.readability = Enums.random(Readability.class);
m.adresse = Enums.random(Adresse.class);
m.returnAddress = Enums.random(ReturnAddress.class);
retourner m ;
}
générateur public static Iterable<Mail> (nombre final d'int) {
renvoyer un nouveau Iterable<Mail>() {
int n = nombre ;
public Iterator<Mail> iterator() {
renvoyer un nouveau Iterator<Mail>() {
public boolean hasNext() { return n-- > 0 }
public Mail next() {return randomMail();
public void remove() { // Non implémenté
lancer une nouvelle UnsupportedOperationException();
}
} ;
}
} ;
}
}
bureau de poste de classe publique {
enum Gestionnaire de courrier {
GÉNÉRAL_DELIVERY {
handle booléen (Mail m) {
commutateur (m.generalDelivery) {
cas OUI :
print("Utilisation de la livraison générale pour " + m);
renvoie vrai ;
par défaut : return false ;
}
}
},
MACHINE_SCAN {
handle booléen (Mail m) {
commutateur (m.scannabilité) {
cas UNSCANNABLE : return false ;
défaut:
commutateur (adresse m.) {
cas INCORRECT : return false ;
défaut:
print("Livraison automatique de "+ m + "");
renvoie vrai ;
}
}
}
},
INSPECTION_VISUELLE {
handle booléen (Mail m) {
commutateur (m.lisibilité) {
cas ILLISIBLE : return false ;
défaut:
commutateur (adresse m.) {
cas INCORRECT : return false ;
défaut:
print("Livrer " + m + " normalement");
renvoie vrai ;
}
}
}
},
RETURN_TO_SENDER {
handle booléen (Mail m) {
switch(m.returnAddress) {
cas MANQUANT : return false ;
défaut:
print("Renvoi de " + m + " à l'expéditeur");
renvoie vrai ;
}
}
} ;
handle booléen abstrait (Mail m);
}
handle de vide statique (Mail m) {
pour (gestionnaire MailHandler : MailHandler.values())
si (gestionnaire. poignée (m))
retour;
print(m + " est une lettre morte");
}
public static void main (String[] arguments) {
pour(Mail mail : Mail.generator(10)) {
print(mail.details());
gérer(courrier);
imprimer("*****");
}
}
} /* Sortir:
Courrier 0, Livraison générale : NO2, Numérisation de l'adresse : NON NUMÉRISABLE, Lisibilité de l'adresse : OUI3, Adresse de l'adresse : OK1, Adresse de retour : OK1
Livrer le courrier 0 normalement
*****
Courrier 1, Livraison générale : NO5, Numérisation de l'adresse : OUI3, Lisibilité de l'adresse : ILLISIBLE, Adresse Adresse : OK5, Adresse de retour : OK1
Remise automatique du courrier 1
*****
Courrier 2, Livraison générale : OUI, Numérisation d'adresse : OUI3, Lisibilité d'adresse : OUI1, Adresse d'adresse : OK1, Adresse de retour : OK5
Utiliser la livraison générale pour Mail 2
*****
Courrier 3, Livraison générale : NO4, Numérisation de l'adresse : OUI3, Lisibilité de l'adresse : OUI1, Adresse de l'adresse : INCORRECT, Adresse de retour : OK4
Renvoi du courrier 3 à l'expéditeur
*****
Courrier 4, Livraison générale : NO4, Numérisation de l'adresse : NON NUMÉRISABLE, Lisibilité de l'adresse : OUI1, Adresse de l'adresse : INCORRECT, Adresse de retour : OK2
Renvoi du courrier 4 à l'expéditeur
*****
Courrier 5, Livraison générale : NO3, Numérisation de l'adresse : OUI1, Lisibilité de l'adresse : ILLISIBLE, Adresse Adresse : OK4, Adresse de retour : OK2
Livraison automatique de Mail 5
*****
Courrier 6, Livraison générale : OUI, Numérisation de l'adresse : OUI4, Lisibilité de l'adresse : ILLISIBLE, Adresse Adresse : OK4, Adresse de retour : OK4
Utiliser la livraison générale pour Mail 6
*****
Courrier 7, Livraison générale : OUI, Numérisation de l'adresse : OUI3, Lisibilité de l'adresse : OUI4, Adresse de l'adresse : OK2, Adresse de retour : MANQUANTE
Utiliser la livraison générale pour Mail 7
*****
Courrier 8, Livraison générale : NO3, Numérisation de l'adresse : OUI1, Lisibilité de l'adresse : OUI3, Adresse de l'adresse : INCORRECT, Adresse de retour : MANQUANTE
Le courrier 8 est une lettre morte
*****
Courrier 9, Livraison générale : NO1, Numérisation de l'adresse : NON NUMÉRISABLE, Lisibilité de l'adresse : OUI2, Adresse de l'adresse : OK1, Adresse de retour : OK4
Livrer Mail 9 normalement
*****
*///:~
Le type énumération est également un type idéal pour créer une machine à états. Une machine à états peut se déplacer entre un nombre limité d'états en fonction de l'entrée, puis terminer le travail une fois qu'un certain état est atteint. sortie correspondante. Un distributeur automatique est un exemple de machine à états typique où nous définissons différentes entrées au sein d'une énumération :
Copiez le code comme suit :
// : énuméré/Input.java
paquet énuméré ;
importer java.util.* ;
entrée d'énumération publique {
NICKEL (5), DIME (10), QUART (25), DOLLAR (100), DENTIFRICE (200), CHIPS (75), SODA (100), SOAP (50), ABORT_TRANSACTION {
public int montant() { // Interdire
throw new RuntimeException("ABORT.amount()");
}
},
STOP { // Cela doit être la dernière instance.
public int montant() { // Interdire
lancer une nouvelle RuntimeException("SHUT_DOWN.amount()");
}
} ;
valeur int ; // En centimes
Entrée (valeur int) { this.value = valeur }
Saisir() {}
int montant() { valeur de retour }; // En centimes
Rand aléatoire statique = new Random (47);
entrée statique publique randomSelection() {
// N'inclut pas STOP :
valeurs de retour()[rand.nextInt(values().length - 1)];
}
} ///:~
VendingMachine est utilisé pour répondre à l'entrée. Tout d'abord, il classe l'entrée via l'énumération Category, puis utilise l'instruction switch :
Copiez le code comme suit :
// : énuméré/VendingMachine.java
// {Args : VendingMachineInput.txt}
paquet énuméré ;
importer java.util.* ;
importer net.mindview.util.* ;
importer un énumération statique.Input.* ;
importer un net.mindview.util.Print.* statique;
énumération Catégorie {
ARGENT(NICKEL, DIME, QUARTER, DOLLAR),ITEM_SELECTION(DENTIFRICE, CHIPS, SODA, SAVON),QUIT_TRANSACTION(ABORT_TRANSACTION),SHUT_DOWN(STOP);
valeurs input[] privées ;
Catégorie(Entrée... types) { valeurs = types }
catégories EnumMap<Input,Category> statiques privées = new EnumMap<Input,Category>(Input.class);
statique {
pour (Catégorie c : Category.class.getEnumConstants())
pour (Type d'entrée : c.values)
catégories.put(type, c);
}
catégorie statique publique catégoriser (entrée d'entrée) {
return catégories.get (entrée);
}
}
Machine distributrice de classe publique {
État statique privé = State.RESTING ;
montant int statique privé = 0 ;
sélection d'entrée statique privée = null ;
enum StateDuration {TRANSIENT} //Énumération de marquage
énumération État {
REPOS {
void next (Entrée entrée) {
commutateur (Catégorie.categorize (entrée)) {
cas ARGENT :
montant += input.montant();
état = ADDING_MONEY ;
casser;
cas SHUT_DOWN :
état = TERMINAL ;
défaut:
}
}
},
ADDING_MONEY {
void next (Entrée entrée) {
commutateur (Catégorie.categorize (entrée)) {
cas ARGENT :
montant += input.montant();
casser;
cas ITEM_SELECTION :
sélection = entrée ;
si (montant < sélection.montant ())
print("Argent insuffisant pour " + sélection);
sinon état = DISTRIBUTION ;
casser;
cas QUIT_TRANSACTION :
état = GIVING_CHANGE ;
casser;
cas SHUT_DOWN :
état = TERMINAL ;
défaut:
}
}
},
DISTRIBUTION (StateDuration.TRANSIENT) {
annuler suivant() {
print("voici votre " + sélection);
montant -= sélection.montant();
état = GIVING_CHANGE ;
}
},
GIVING_CHANGE(StateDuration.TRANSIENT) {
annuler suivant() {
si (montant > 0) {
print("Votre monnaie : " + montant);
montant = 0 ;
}
état = REPOS;
}
},
TERMINAL { void output() { print("Halté"); } };
privé booléen isTransient = false ;
État() {}
État (StateDuration trans) { isTransient = true }
void next (Entrée entrée) {
throw new RuntimeException("Appelez uniquement " + "next(Input input) pour les états non transitoires");
}
annuler suivant() {
throw new RuntimeException("Appelez uniquement next() pour " + "StateDuration.TRANSIENT states");
}
void output() { print(montant);
}
static void run(Générateur<Input> gen) {
while(state != State.TERMINAL) {
state.next(gen.next());
pendant que (état.isTransient)
état.next();
état.output();
}
}
public static void main (String[] arguments) {
Generator<Input> gen = new RandomInputGenerator();
si (arguments. longueur == 1)
gen = nouveau FileInputGenerator(args[0]);
exécuter(gén);
}
}
// Pour une vérification de base :
la classe RandomInputGenerator implémente Generator<Input> {
public Input next() {returnInput.randomSelection();
}
// Crée des entrées à partir d'un fichier de chaînes séparées par ';' :
la classe FileInputGenerator implémente Generator<Input> {
entrée privée Iterator<String> ;
public FileInputGenerator (String fileName) {
input = new TextFile(fileName, ";").iterator();
}
entrée publique suivant() {
si(!input.hasNext())
renvoie null ;
return Enum.valueOf(Input.class, input.next().trim());
}
} /* Sortir:
voici vos CHIPS
voici votre DENTIFRICE
Votre monnaie : 35
Argent insuffisant pour SODA
Argent insuffisant pour SODA
Votre monnaie : 75
Arrêté
*///:~
Voici les données de test utilisées pour générer le résultat ci-dessus :
Copiez le code comme suit :
TRIMESTRE ; TRIMESTRE ; PUCES ;
DOLLARS ; DENTIFRICE ;
TRIMESTRE ; DIME ; ABORT_TRANSACTION ;
QUART ; DIME ; SODA ;
QUART ; DIME ; NICKEL ;
ABORT_TRANSACTION ;
ARRÊT;
///:~
Déballage multiple Lorsqu'il s'agit d'interactions entre plusieurs types, le code risque de devenir compliqué, comme Number.plush(Number), Number.mutiply(Number), etc. Number n'est qu'une classe de base de la famille, donc lorsque vous appelez Lorsque a.plus(b), vous ne connaissez ni le type de a ni le type de b, alors comment vous assurer que l'interaction entre eux est correcte ? Java ne peut effectuer qu'un seul déballage, c'est-à-dire que si une ou plusieurs opérations sur plusieurs types inconnus sont effectuées, Java ne peut effectuer un mécanisme de liaison dynamique que sur l'un des types, ce qui ne peut pas résoudre le problème dont nous avons parlé ci-dessus. pour écrire manuellement le code de liaison dynamique.
La solution consiste à utiliser la liaison multiple. Le polymorphisme ne peut se produire que lors de l'appel d'une méthode, donc si vous avez besoin de plusieurs décompressions, vous devez appeler plusieurs méthodes. Avec le déballage multiple, vous devez disposer d'une méthode virtuelle qui appelle la méthode de chaque type à déballer. L’exemple suivant est un exemple pierre-papier-ciseaux :
Copiez le code comme suit :
// : énuméré/Résultat.java
paquet énuméré ;
résultat de l'énumération publique { GAGNER, PERDRE, TIRER } ///:~
// : énuméré/RoShamBo1.java
// Démonstration de dispatching multiple.
paquet énuméré ;
importer java.util.* ;
importer un énumération statique.Résultat.* ;
élément d'interface {
Résultat rivaliser(Article il);
Évaluation des résultats (document p);
Évaluation des résultats (ciseaux);
Évaluation des résultats (Rock r);
}
class Paper met en œuvre l'article {
public Résultat concurrence (Item it) { return it.eval (this });
évaluation des résultats publics (Papier p) { return DRAW }
évaluation des résultats publics (ciseaux) { return WIN }
évaluation des résultats publics (Rock r) { return LOSE ;
public String toString() { return "Papier" ;
}
classe Ciseaux met en œuvre l'article {
public Résultat concurrence (Item it) { return it.eval (this });
évaluation des résultats publics (Papier p) { return LOSE ;
évaluation publique des résultats (ciseaux) { return DRAW }
évaluation des résultats publics (Rock r) { return WIN ;
public String toString() { return "Ciseaux" ;
}
la classe Rock implémente l'article {
public Résultat concurrence (Item it) { return it.eval (this });
évaluation des résultats publics (Papier p) { return WIN ;
évaluation des résultats publics (ciseaux) { return LOSE }
évaluation des résultats publics (Rock r) { return DRAW }
public String toString() { return "Rock";
}
classe publique RoShamBo1 {
statique final int SIZE = 20 ;
rand aléatoire statique privé = new Random (47);
élément statique public newItem() {
commutateur(rand.nextInt(3)) {
défaut:
cas 0 : renvoie de nouveaux ciseaux ();
cas 1 : renvoyer un nouveau papier ();
cas 2 : renvoie new Rock();
}
}
correspondance vide statique publique (élément a, élément b) {
System.out.println(a + " contre " + b + " : " + a.compete(b));
}
public static void main (String[] arguments) {
pour(int i = 0; i < TAILLE; i++)
match(newItem(), newItem());
}
} /* Sortir:
Rock contre Rock : TIRAGE
Papier contre pierre : GAGNER
Papier contre pierre : GAGNER
Papier contre pierre : GAGNER
Ciseaux contre papier : GAGNEZ
Ciseaux contre ciseaux : TIRER
Ciseaux contre papier : GAGNEZ
Pierre contre papier : PERDRE
Papier contre papier : DESSINER
Pierre contre papier : PERDRE
Papier contre ciseaux : PERDRE
Papier contre ciseaux : PERDRE
Pierre contre ciseaux : GAGNEZ
Pierre contre papier : PERDRE
Papier contre pierre : GAGNER
Ciseaux contre papier : GAGNEZ
Papier contre ciseaux : PERDRE
Papier contre ciseaux : PERDRE
Papier contre ciseaux : PERDRE
Papier contre ciseaux : PERDRE
*///:~
Nous avons utilisé de nombreuses méthodes pour réaliser plusieurs décompressions, mais nous avons obtenu une bonne structure de code. Le plus gros problème lors de l'utilisation d'une solution d'énumération pour implémenter le code ci-dessus est que l'instance d'énumération n'est pas un type, donc l'instance d'énumération ne peut pas être utilisée comme type de paramètre. Mais nous pouvons toujours avoir d'autres moyens de contourner cet obstacle.
Copiez le code comme suit :
//: énuméré / roshambo2.java
// changeant une énumération sur un autre.
package énuméré;
importer statique énuméré.
L'énumération publique Roshambo2 implémente le concurrent <Roshambo2> {
Paper (Draw, perdre, gagner), ciseaux (gagner, tirer, perdre), rock (perdre, gagner, tirer);
Résultat privé VPaper, Vscissors, Vrock;
Roshambo2 (papier de résultat, ciseaux de résultats, résultats de résultat) {
this.vpaper = papier;
this.vscissors = ciseaux;
this.vrock = rock;
}
Résultats du public Affronter (Roshambo2 it) {
commutateur (it) {
défaut:
Document de cas: retour en VPaper;
ciseaux de cas: renvoyer des VScissors;
Case Rock: Retour Vrock;
}
}
public static void main (String[] arguments) {
Roshambo.Play (Roshambo2.class, 20);
}
} /* Sortir:
Rock vs Rock: Draw
Ciseaux contre Rock: perdre
Ciseaux contre Rock: perdre
Types énumérés 753
Ciseaux contre Rock: perdre
Papier vs ciseaux: perdre
Papier vs papier: dessiner
Papier vs ciseaux: perdre
Rock vs ciseaux: gagner
Ciseaux vs ciseaux: Draw
Rock vs ciseaux: gagner
Ciseaux contre papier: gagner
Ciseaux contre papier: gagner
Rock vs papier: perdre
Rock vs ciseaux: gagner
Ciseaux contre Rock: perdre
Papier vs ciseaux: perdre
Ciseaux contre papier: gagner
Ciseaux contre papier: gagner
Ciseaux contre papier: gagner
Ciseaux contre papier: gagner
* ///: ~
Copiez le code comme suit :
//: énuméré / concurrent.java
// changeant une énumération sur un autre.
package énuméré;
Interface publique Le concurrent <T étend le concurrent <T>> {
Résultat CONTENUE (T CONCURTITH);
} ///: ~
Copiez le code comme suit :
//: énuméré / roshambo.java
// Outils communs pour les exemples de Roshambo.
package énuméré;
importer net.mindview.util. *;
classe publique Roshambo {
Le public statique <T étend le concurrent <T>> Match de vide (t a, t b) {
System.out.println (a + "vs" + b + ":" + a.compte (b));
}
Le public statique <T étend enum <T> & le concurrent <T>> VOID Play (classe <T> RSBClass, int Size) {
pour (int i = 0; i <size; i ++)
match (enums.random (RSBClass), enums.random (RSBClass));
}
} ///: ~
Étant donné que la formulation de méthodes statiques peut fournir différentes méthodes pour chaque type d'énumération, cela semble être une bonne solution pour obtenir un déballage multiple, mais nous sommes toujours confrontés au problème que l'instance d'énumération n'est pas un type, donc tout ce que nous pouvons faire est d'ajouter une instruction Switch :
Copiez le code comme suit :
//: énuméré / roshambo3.java
// en utilisant des méthodes spécifiques à constante.
package énuméré;
importer statique énuméré.
L'énumération publique Roshambo3 implémente le concurrent <Roshambo3> {
PAPIER {
Résultats publics CONTIONNEMENT (ROSHAMO3 IT) {
commutateur (it) {
par défaut: // pour placer le compilateur
Papier de cas: tirage de retour;
ciseaux de cas: retour perd;
Case Rock: Return Win;
}
}
},
CISEAUX {
Résultats publics CONTIONNEMENT (ROSHAMO3 IT) {
commutateur (it) {
défaut:
Document de cas: victoire de retour;
ciseaux de cas: tirage de retour;
Case Rock: Retour perdre;
}
}
},
ROCHER {
Résultats publics CONTIONNEMENT (ROSHAMO3 IT) {
commutateur (it) {
défaut:
Papier de cas: retour perd;
ciseaux de cas: victoire de retour;
Case Rock: Retour Draw;
}
}
} ;
Résultats abstraits publics CONTENUE (ROSHAMO3 IT);
public static void main (String[] arguments) {
Roshambo.Play (Roshambo3.class, 20);
}
} / * Même sortie que Roshambo2.java * ///: ~
Le code suivant est une méthode d'implémentation plus concise:
Copiez le code comme suit :
//: énuméré / roshambo4.java
package énuméré;
L'énumération publique Roshambo4 implémente le concurrent <Roshambo4> {
ROCHER {
Résultats du public Créée (adversaire de Roshamo4) {
return somper (ciseaux, adversaire);
}
},
CISEAUX {
Résultats du public Créée (adversaire de Roshamo4) {
RETOUR CONTIFICATION (PAPIER, adversaire);
}
},
PAPIER {
Résultats du public Créée (adversaire de Roshamo4) {
Retour CONTIONS (Rock, adversaire);
}
} ;
Résultat CONTIONNEMENT (LOSER ROSHAMO4, ROSHAMO4 AVPPOSANT) {
return ((adversaire == this)? résultat.Draw: ((adversaire == loser)? résultat.win: résultat.lose));
}
public static void main (String[] arguments) {
Roshambo.Play (Roshambo4.Class, 20);
}
} / * Même sortie que Roshambo2.java * ///: ~
La classe Enuummap semble être un bon moyen d'implémenter un déballage multiple:
Copiez le code comme suit :
//: énuméré / roshambo5.java
// Dispatting multiple à l'aide d'un énumap d'énumaps.
package énuméré;
importer java.util.* ;
importer statique énuméré.
ENUM ROSHAMO5 implémente le concurrent <Roshambo5> {
Papier, ciseaux, rocher;
Enuummap statique <Roshambo5, Enummap <Roshambo5, résultat >> Table = Nouveau Entummap <Roshambo5, Enummap <Roshambo5, résultat >> (Roshambo5.class);
statique {
pour (Roshambo5 it: roshambo5.Values ())
Table.put (It, New Enummap <Roshambo5, résultat> (Roshambo5.class));
initrow (papier, tirage, perdre, gagner);
initrow (ciseaux, victoire, tirage, perdre);
initrow (rock, perdre, victoire, tirage);
}
statique void initrow (roshambo5 it, résultat vpaper, résultat vscissors, résultat vrock) {
Enuummap <Roshambo5, résultat> row = roshambo5.Table.get (it);
Row.put (Roshambo5.paper, vpaper);
row.put (roshambo5.scissors, vscissors);
Row.put (Roshambo5.Rock, vrock);
}
Résultats du public rivaliser (roshambo5 it) {
return table.get (this) .get (it);
}
public static void main (String[] arguments) {
Roshambo.Play (Roshambo5.class, 20);
}
} / * Même sortie que Roshambo2.java * ///: ~
Nous pouvons également utiliser la fonctionnalité des instances d'énumération avec des valeurs fixes pour utiliser des données pour la méthode d'implémentation la plus simple.
Copiez le code comme suit :
//: énuméré / roshambo6.java
// Énule à l'aide de "tables" au lieu de plusieurs répartitions.
package énuméré;
importer statique énuméré.
ENUM ROSHAMO6 implémente le concurrent <Roshambo6> {
Papier, ciseaux, rocher;
Résultat statique privé [] [] Tableau = {
{Dessiner, perdre, gagner}, // papier
{Gagner, tirer, perdre}, // ciseaux
{Perdre, gagner, tirer}, // rock
} ;
Résultats publics CONTIONS (ROSHAMO6 AUTR) {
Tableau de retour [this.OrDinal ()] [autre.Ordinal ()];
}
public static void main (String[] arguments) {
Roshambo.play (Roshambo6.class, 20);
}
} ///: ~