enum replacing class

Figure 371. enum Day replacing public class Day Slide presentation
public enum Day {

  MONDAY("Monday"),
  TUESDAY("Tuesday"),
  ...
  SUNDAY("Sunday");

  final String name;
  Day(final String name) { this.name = name;}

  public String toString() { return name;}
}

Figure 372. switch statements working again Slide presentation
public enum Day {
...
  public static String getItalianDayName(final Day day) {
    switch (day) {
      case MONDAY:    return "Lunedì";
      case TUESDAY:   return "Martedì";
   ...
      case SUNDAY:    return "Domenica";
    }
    return null; // Actually unreachable, but static
                 // compiler code analysis is limited
  }
}

Figure 373. enum constructor being implicitly private Slide presentation
public enum Day {
  ...
  private Day(final String name)
    { ...

Compile time warning:

Modifier 'private' is redundant for enum constructors

public enum Day {
  ...
  public Day(final String name)
    { ...

Compile time error:

Modifier 'public' not allowed here

Prohibits enum external instance creation.


exercise No. 124

Compass directions

Q:

We consider an eight direction compass rose:

Provide an enum Direction to be usable in the following manner:

final Direction northWest = Direction.NW;

System.out.println(northWest);
north by west (315°)

Tip

Provide an appropriate constructor among with suitable «internal» instance attributes and a corresponding toString() method.

A:

The desired output contains both a given direction's oral description and a 0 - 360° degree value. We thus start by:

public enum Direction {
  int degree;
  String fullName;
}

For creating a Direction instance a constructor accepting both values is being required:

public enum Direction {

  N(0, "north"); 

  Direction(final int degree, final String fullName) { 
    this.degree = degree;
    this.fullName = fullName;
  }

  public final int degree; 
  public final String fullName;
}

For the sake of simplicity we only create the «north» direction here.

Constructor accepting:

  1. A degree value e.g. 90° representing «eastern» direction.

  2. An informal name e.g. «east».

Two public attributes representing both a direction's degree value and its informal name.

For creating output texts like e.g. north by west (315°) we need a toString() method. Also adding the yet missing directions our final result looks like:

public enum Direction {

  N(   0, "north"),
  NE( 45, "north by east"),
  E(  90, "east"),
  SE(135, "south by east"),
  S( 180, "south"),
  SW(225, "south by west"),
  W( 270, "west"),
  NW(315, "north by west");

  Direction(final int degree, final String fullName) {
    this.degree = degree;
    this.fullName = fullName;
  }

  @Override
  public String toString() {
    return fullName + " (" + degree + "°)";
  }

  public final int degree;
  public final String fullName;
}

exercise No. 125

Compass direction neighbours

Q:

We would like to «invert» a given direction e.g. turning N to S and vice versa. Extend Compass direction neighbours by adding an opposite() method to be used like:

final Direction southWest = Direction.SW;

System.out.println("Direction: " + southWest);
System.out.println(" Opposite: " + southWest.opposite());
Direction: south by west (225°)
 Opposite: north by east (45°)

Tip

  • Consider the method public static T[] values() being added by the compiler implicitly to any enum class. See the method 's valueOf() explanation. It allows you to access the array of all instances of a given enum.

  • The ordinal() method returns a given enum's instance index with respect to the order of appearance. Using the above values() method you can thus access any index by its value. Use this to calculate the opposite compass direction's index value.

A:

Using a switch allows for a straightforward and simple solution:

public enum Direction {
  ...
  public Direction opposite() {
    switch (this) {
      case N:  return S;
      case NE: return SW;
      case E:  return W;
      case SE: return NW;
      case S:  return N;
      case SW: return NE;
      case W:  return E;
      case NW: return SE;

      default: return null; // Unreachable, but required for keeping the compiler happy.
    }
  }
  ...
}

Using the hint we may instead calculate the opposing direction:

public Direction opposite() {
  return values()[ (ordinal() + 4) % 8];
}