When you first use enumerated types, you might simply see them as an alternative to using constants. However they have other interesting uses. For example, you can change the behavior of a class based on the value of an enumerated type. This tip will show You How to Implement Enumeration Constant-Specific Behavior in An Elegant Way.
Begin by Creating A Simple ENUM TYPE THAT REPRESENTS The Four Basic Types of u.s. COINS:
Public enum coin1 {
Penny,
Nickel,
DIME,
Quarter;
}
You can now switch on the value of an enum. For example, you can create a method getValue () That Accepts an Object of Type Coin1:
Static int getValue (COIN1 COIN) {
Switch (coin) {
Case Penny: // Do Something
// .. Remaining Cases
}
}
You Can Also Itereate Through The Different Values In Coin1 Using The Enhanced for:
For1 Coin: Coin1.VALUES ())
Let's put those two techniques together Into aclient for coin1:
Public class dispenser1 {
Static int getValue (COIN1 COIN) {
Switch (coin) {
Case Penny: Return 1;
Case nickel: return 5;
Case Dime: Return 10;
Case Quarter: Return 25;
DEFAULT: RETURN 0;
}
}
Public static void main (String [] args) {
For (COIN1 COIN: COIN1.VALUES ()) {
System.out.println ("a" coin "HAS Value ="
GetValue (COIN) ".");
}
}
}
In this Example, The Default Method Returns a value of 0. In Production Code, you might prefer to have the default copy throw an exception.
The value of coin.tostring () Is The Name of The Enum Instance, So The Output Will Love LOKE THIS:
A Penny Has Value = 1.
A nickel haas value = 5.
A DIME HAS value = 10.
A quarter HAS value = 25.
In a straightforward example like the previous one, the switch statement can easily be moved from the client class to the enumeration class, so that the switch information is part of the Coin enum's functionality. Later, you will see an example where you need the client to switch on the enumeration type and decide what to do itself. in Coin1, each type has a single behavior, so let's move the switch statement to the enum. This is shown in the enum Coin2, where the switch statement is in the value ( ) method of the enum class.Newcomers to enumerated types think of them as representing constants, and forget that you can add methods to the definition. Remember that enums have the flexibility of classes and so you have many choices regarding how or when to implement different .....................
Public enum coin2 {
Penny,
Nickel,
DIME,
Quarter;
Int value () {
Switch (this) {
Case Penny: Return 1;
Case nickel: return 5;
Case Dime: Return 10;
Case Quarter: Return 25;
DEFAULT: RETURN 0;
}
}
}
Now The Client Code Can Be Simplified:
Public class dispenser2 {
Public static void main (String [] args) {
For (COIN2 COIN: COIN2.VALUES ()) {
System.out.println ("a" coin "HAS Value ="
COIN.VALUE () ".");
}
}
}
You can eliminate the switch statement entirely by specifying different behavior within constant-specific methods. Make value () abstract so that it can be called by client code. Defining the method in the enum itself guarantees that it can be called on any constant. Declaring The Method Abstract Ensures Each Constant Will Override The IMPLEMentation.
Public enum coin3 {
Penny {int value () {return 1;}}, nickel {int value () {return 5;}}
Dime {Int value () {return 10;}},
Quarter {int value () {return 25;}};
Abstract Int value ();
}
You Can Call Coin3 by Changing The Appropriate Line of Dispensers2 TO:
For (COIN3 COIN: COIN3.VALUES ())
ENUMERATED TYPS CAN Also Contain Constructors. You Can Supply Coin3 with a Field Named CoinValue That Holds An Int and IS Set by a Construction:
Private coin3 (int value) {
CoinValue = VALUE;
}
The private keyword is superfluous here because enum constructors are implicitly private. It is included here as a visual reminder that the constructor can not be explicitly called (it is dropped in the code listing below).
Now The value () Method Just Returns CoinValue. The Other Change Is That Each Class Must Set CoinValue. You do this by changing the list from:
Penny, Nickel, DIME, Quarter;
TO:
Penny (1), Nickel (5), DIME (10), Quarter (25);
Here is the modified version of coin3:
Public enum coin3 {
Penny (1),
Nickel (5),
DIME (10),
Quarter (25);
Private int coinvalue;
Int value () {return coinvalue;}
COIN3 (int value) {
CoinValue = VALUE;
}
}
Let's return to the case where you might want different behavior in the client depending on the enumeration type. For example, if you had an Employee enum, you might need to vary behavior in different parts of a human resources application depending on whether the Employee type was SALARY, HOURLY, or HOURLY_PART_TIME. This difference might be applicable in the calculation of days off, bonuses, benefits, and pay. You do not want to implement a switch statement in each client that calls different methods based on the type that is called. Ideally, you would like the correct method to be called automatically based on the type.One way to accomplish this is by implementing the Visitor pattern. A classic reference is Design Patterns, Elements of Reusable Object-Oriented Software by Gamma, Helm, Johnson, And Vlissides. There Are Variants on the Visitor Pattern - Only One Version Is Discussed in this Tip. The point of buy it here is what if you use the visitor pattern with enums, Any Enum Con Stant-Specific Function (And Any Number of these Functions) can be used by using a visitist.
If you have never seen the Visitor pattern before, you might find it a bit confusing An instance of the enumerated type is created, and a method is called -.. In this case, accept () The class containing the behavior is passed in AS An Argument. The appropriate Method In The Appropriate Method In The Containing The Behavior. in this Way, Different Behavior Can Be Injected Into a Client Class.
The first component is the enumerated type. This time acception () IS An Abstract Method That Is Implement. For Example, In Penny, Accept () IS IMPLEMENTED AS FOLLOWS:
void accept (CoinVisitor cv) {cv.visitPenny (this); In other words, this instance of accept calls the visitPenny () method in the CoinVisitor instance that was passed in as a parameter Here is the revised enum class:.
Public enum coin4 {
Penny {
Void Accept (COINVISIOR CV) {CV.VisiTpenny (this);
}
Nickel {
Void Accept (COINVISITOR CV) {CV.Visitnickel (this);}
}
DIME {
Void Accept (COINVISITOR CV) {cv.visitdime (this);
}
Quarter {
Void Accept (COINVISITOR CV) {CV.visitquarter (this);
}
Abstract Void Accept (Coinvisitor CV);
}
In this case, there is only a single implementation of CoinVisitor so you could create a concrete class. But the point of this example is to show how you can set up the infrastructure to vary the behavior in a client class. So you will need the FOLLOWING ABSTRACT CLASS:
Public Abstract Class Coinvisitor {
Void Visitpenny (COIN4 C) {}
Void Visitnickel (COIN4 C) {}
Void VisitDime (COIN4 C) {}
Void Visitquarter (COIN4 C) {}
}
Now any Time You Want To Specify A Particular Behavior That Varies for Each of The Coin4 Types for EACH OF THE COIN4 TYPES, YOU EXTEND COINVISIOR. For Example, CoinVisitor Prints Out the name and value of the appropriate coin.
Public class coinvaluevisitor eXtends coinvisitor {
Void Visitpenny (COIN4 C) {
System.out.println ("A Penny Has Value = 1.");
}
Void Visitnickel (COIN4 C) {
System.out.println ("a nickel haas value = 5.");
}
Void VisitDime (COIN4 C) {
System.out.println ("A DIME HAS VALUE = 10);
}
Void Visitquarter (COIN4 C) {
System.out.println ("a quarter Has value = 25.");
}
}
The client code still iterates through the values of the enum, but this time, if coin is an instance of Coin4 and cvv is an instance of the CoinValueVisitor, you initiate the correct behavior with the following call: coin.accept (cvv);
If Coin Is An Instance of Penny, THIS CALL HAS The Effect of Calling The Accept () Method in Penny, And Passing In Cv. THEN CALED ON CVV. THIS RESULTS in The Printing of "a Penny HAS Value = 1. "To standard out. Here is the revised class.
Public class dispenser4 {
Public static void main (String [] args) {
CoinValuevisitor CVV = New CoinValuevisitor ();
For (COIN4 COIN: COIN4.VALUES ()) {
Coin.accept (CVV);
}
}
}
The result is the backing output:
A Penny Has Value = 1.
A nickel haas value = 5.
A DIME HAS value = 10.
A quarter HAS value = 25.