I\'m programming a game in java which is made up of a grid of tiles. I wan\'t to be able to inuitively define the edges of the tiles and how they relate to each other, e.g.
public enum Edge {
TOP,
BOTTOM(Edge.TOP),
LEFT,
RIGHT(Edge.LEFT);
private Edge opposite;
private Edge() {
}
private Edge(Edge opp) {
this.opposite = opp;
opp.opposite = this;
}
public Edge opposite() {
return this.opposite;
}
}
You can do this which is not as intuitive.
public enum Edge {
TOP, BOTTOM, LEFT, RIGHT;
private Edge opposite;
static {
TOP.opposite = BOTTOM;
BOTTOM.opposite = TOP;
LEFT.opposite = RIGHT;
RIGHT.opposite = LEFT;
}
public Edge opposite(){
return this.opposite;
}
}
Here's another way
public enum Edge {
TOP("BOTTOM"),
BOTTOM("TOP"),
LEFT("RIGHT"),
RIGHT("LEFT");
private String opposite;
private Edge(String opposite){
this.opposite = opposite;
}
public Edge opposite(){
return valueOf(opposite);
}
}
Peter Lawrey's solution is however more efficient and compiletime safe.
I preferred this:
public enum Edge {
TOP,
BOTTOM,
LEFT,
RIGHT;
private Link link;
private Link getLink() {
if (link == null) {
link = Link.valueOf(name());
}
return link;
}
public Edge opposite() {
return getLink().opposite();
}
}
public enum Link {
TOP(Edge.BOTTOM),
BOTTOM(Edge.TOP),
LEFT(Edge.RIGHT),
RIGHT(Edge.LEFT);
private Edge opposite;
private Link(Edge opp) {
this.opposite = opp;
}
public Edge opposite() {
return this.opposite;
}
}
You can create a static Map
where key is the original enum and the value the opposite edge. Initialize it in a static block and the return the mapping from the opposite()
method.
private static Map<Edge, Edge> oppostiteMapping;
static {
oppositeMapping = new EnumMap<Edge, Edge>();
oppositeMapping.put(TOP, BOTTOM);
...
}
public Edge opposite() {
return oppositeMapping.get(this);
}
EDIT: as proposed in comment better to use EnumMap, so I upgraded accordingly
Btw. this approach is generally useful when you create something like static fromString()
method etc.
With Java 8 lambdas:
public enum Edge {
TOP(() -> Edge.BOTTOM),
BOTTOM(() -> Edge.TOP),
LEFT(() -> Edge.RIGHT),
RIGHT(() -> Edge.LEFT);
private Supplier<Edge> opposite;
private Edge(Supplier<Edge> opposite) {
this.opposite = opposite;
}
public Edge opposite() {
return opposite.get();
}
}