I have an enum for which each element has an opposite. I'd like an elegant way to encapsulate this inside each element of the enum. My preferred options is not legal as it uses forward references.
enum Direction {
NORTH(SOUTH), SOUTH(NORTH), EAST(WEST), WEST(EAST);
private final Direction opposite;
Direction(Direction opposite) {
this.opposite = opposite;
}
public Direction getOpposite() {
return opposite;
}
}
Using a supplier is also illegal.
enum Direction {
NORTH(() -> SOUTH), SOUTH(() -> NORTH), EAST(() -> WEST), WEST(() -> EAST);
private final Supplier<Direction> opposite;
Direction(Supplier<Direction> opposite) {
this.opposite = opposite;
}
public Direction getOpposite() {
return opposite.get();
}
}
Which leaves me with overriding the method:
enum Direction {
NORTH{
public Direction getOpposite() {
return SOUTH;
}
},
SOUTH{
public Direction getOpposite() {
return NORTH;
}
},
EAST{
public Direction getOpposite() {
return WEST;
}
},
WEST{
public Direction getOpposite() {
return EAST;
}
};
public abstract Direction getOpposite();
}
Using a switch:
enum Direction {
NORTH, SOUTH, EAST, WEST;
public Direction getOpposite() {
return switch(this) {
case NORTH -> SOUTH;
case SOUTH -> NORTH;
case EAST -> WEST;
case WEST -> EAST;
}
}
}
Or a map:
enum Direction {
NORTH, SOUTH, EAST, WEST;
private static final Map<Direction,Direction> OPPOSITES =
Map.of(NORTH, SOUTH, SOUTH, NORTH, EAST, WEST, WEST, EAST);
public Direction getOpposite() {
OPPOSITES.get(this);
}
}
None of the alternatives are as straightforward or readable as just listing the opposite as an argument.
Is there an elegant way to avoid the forward reference issue?