In Java, an enumeration is nothing but that a class either inherits [implicitly] from Enum
. The number of instances of it is fixed, and it may or may not be abstract - the important thing is that all its elements are concrete. That is, if it has abstract methods, then every element needs to have a body [that implements these methods]. Otherwise, they may or may not have.
An enumeration can have everything a class has, including fields and methods.
public enum Planet {
MERCURY (3.303e+23, 2.4397e6),
VENUS (4.869e+24, 6.0518e6),
EARTH (5.976e+24, 6.37814e6),
MARS (6.421e+23, 3.3972e6),
JUPITER (1.9e+27, 7.1492e7),
SATURN (5.688e+26, 6.0268e7),
URANUS (8.686e+25, 2.5559e7),
NEPTUNE (1.024e+26, 2.4746e7);
private final double mass; // in kilograms
private final double radius; // in meters
Planet(double mass, double radius) {
this.mass = mass;
this.radius = radius;
}
private double mass() { return mass; }
private double radius() { return radius; }
// universal gravitational constant (m3 kg-1 s-2)
public static final double G = 6.67300E-11;
double surfaceGravity() {
return G * mass / (radius * radius);
}
double surfaceWeight(double otherMass) {
return otherMass * surfaceGravity();
}
public static void main(String[] args) {
if (args.length != 1) {
System.err.println("Usage: java Planet <earth_weight>");
System.exit(-1);
}
double earthWeight = Double.parseDouble(args[0]);
double mass = earthWeight/EARTH.surfaceGravity();
for (Planet p : Planet.values())
System.out.printf("Your weight on %s is %f%n",
p, p.surfaceWeight(mass));
}
}
Source.
The access control to these methods is the same as that of any class (public
, private
, protected
...). Except for the constructor, which needs to be "default" - i.e. without any modifier - or private, since you cannot call it directly to create new instances of enum
.
An enumeration may have abstract methods in its definition (i.e. the "normal" part of the code); however, each of its elements needs to implement these methods, as each of them is a concrete class and final
:
public enum Choices {
ROCK("rock") {
public List<Choices> getWinsAgainst() { ... }
},
PAPER("paper") { ... }, // Precisa implementar getWinsAgainst
SCISSORS("scissors") { ... }; // Precisa implementar getWinsAgainst
SPOCK("Spock") { ... }, // Precisa implementar getWinsAgainst
LIZARD("lizard") { ... }, // Precisa implementar getWinsAgainst
private String nome;
Choices(String nome) {
this.nome = nome;
}
public abstract List<Choices> getWinsAgainst(); // todos os elementos
// precisam implementar
}
Moreover, every enumeration inherits implicitly from Enum
(i.e. cannot inherit from any other class, but can implement interfaces normally). It has, if I’m not mistaken, a generic type just like the type itself, ex.: enum X extends Enum<X>
, also implicitly established. Every element that has a body has its own class, and it is the only object of it (i.e. Singleton). One cannot inherit from the class of these elements (i.e. are final
), nor of the enum
. Nor can new instances of enum
(i.e. is in fact abstract - although elements without body are instances of it).
On when to use, I would say that only in cases where the number of instances is finite, known at compile time, and unlikely to change in the future. I have difficulty thinking of examples, but think of "natural" sets like the cardinal points (north, south, east, west) or conventions that will hardly be replaced in the future, such as the days of the week (Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday). Personally, I see little use in enum
s (except for the possibility of using it in a switch
, which is not very OO anyway), but someone with more practical experience in Java can know more use cases.