Can enumerations contain methods?

4

I do not know if the term is this, "abstract methods in a enum ".

My question came after seeing this implementation in code review . Until then I had never seen this kind of thing in any tutorial or article pertaining to enum in Java and found it to be sensational. Here is an excerpt:

public enum Choices {
   ROCK("rock") {
       @Override
       public List<Choices> getWinsAgainst() {
          if (winsAgainst.isEmpty()) {
              winsAgainst.add(SCISSORS);
              winsAgainst.add(LIZARD);
          }
          return winsAgainst;
       }
   }

   // restante do código
}
  • Can an enumeration have a method implemented within it?
  • How does access control work for these methods?
  • When to use this practice? Deploy directly to enum to instead of having a class.
  • asked by anonymous 12.12.2014 / 07:21

    1 answer

    4

    In Java, an enumeration is nothing more than 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 must have a body [that implements those methods]. Otherwise, they may or may not.

    • 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));
          }
      }
      

      Font .

      The access control to these methods is the same as that of any class ( public , private , protected ...). Except for the constructor, which must be "standard" - i.e. without any modifier - or private, since you can not call it directly to create new instances of enum .

    • An enumeration can have abstract methods in its definition (i.e. the "normal" part of the code); however, each of its elements needs to implement these methods, since 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
      }
      
    • Furthermore, every enumeration inherits implicitly from Enum (i.e. can not inherit from any other class, but can implement interfaces normally). Possess if I am not mistaken a generic type equal to the type itself, eg enum X extends Enum<X> , also implicitly established. Each element that has a body has its own class, and it is the only object in it (i.e. singleton ). You can not inherit from the class of these elements (i.e. they are final ), nor from enum itself. Also, you can not create new instances of enum (i.e. is abstract in fact - although bodyless elements 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 such as 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 utility in enum s (except for the possibility of using it in switch , which is not very OO anyway), but someone with more hands-on experience in Java may know more use cases. p>     

    12.12.2014 / 08:03