非法转发引用和枚举

我正在编写一个由瓷砖网格组成的游戏。 我不能直接定义瓷砖的边缘以及它们是如何相互关联的,例如,为了得到瓷砖的相反边缘,我想只能inputTOP.opposite() 。 但是,当使用枚举来定义这些边缘时,我最终必须在contstructor中至less转发两个引用的引用:

 public enum Edge { TOP(Edge.BOTTOM), //illegal forward reference BOTTOM(Edge.TOP), LEFT(Edge.RIGHT), //illegal forward reference RIGHT(Edge.LEFT); private Edge opposite; private Edge(Edge opp){ this.opposite = opp; } public Edge opposite(){ return this.opposite; } } 

有没有什么办法使用枚举这个问题一样简单?

你可以做到这一点不直观。

 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; } } 
 enum Edge { TOP { @Override public Edge opposite() { return BOTTOM; } }, BOTTOM { @Override public Edge opposite() { return TOP; } }, LEFT { @Override public Edge opposite() { return RIGHT; } }, RIGHT { @Override public Edge opposite() { return LEFT; } }; public abstract Edge opposite(); } 
 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; } } 

这是另一种方式

 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的解决scheme更高效且编译时更安全。

您也可以在枚举中使用静态内部类:

 public enum EnumTest { NORTH( Orientation.VERTICAL ), SOUTH( Orientation.VERTICAL ), EAST( Orientation.HORIZONTAL ), WEST( Orientation.HORIZONTAL ); private static class Orientation { private static final String VERTICAL = null; private static final String HORIZONTAL = null; } } 

从这里偷来 🙂

你可以定义一个类似于下面的方法。

 public enum Edge { TOP, BOTTOM, LEFT, RIGHT; public Edge opposite() { switch (this) { case TOP: return Edge.BOTTOM; case BOTTOM: return Edge.TOP; case LEFT: return RIGHT; case RIGHT: return LEFT; default: throw new RuntimeException("Oh dear"); } } } 

您可以创build一个静态的Map ,其中键是原始枚举,而值是相反的边缘。 在一个静态块中初始化它,并返回来自opposite()方法的映射。

 private static Map<Edge, Edge> oppostiteMapping; static { oppositeMapping = new EnumMap<Edge, Edge>(); oppositeMapping.put(TOP, BOTTOM); ... } public Edge opposite() { return oppositeMapping.get(this); } 

编辑:如评论中提出更好地使用EnumMap,所以我相应地升级

顺便说一句。 当你创build类似静态的fromString()方法等时,这种方法通常是有用的。

您可以使用内部映射来定义这些关联。 如果在初始化Map的时候,你已经创build了所有的枚举值:

 public enum Edge { TOP, BOTTOM, LEFT, RIGHT; private static final Map<Edge, Edge> opposites = new EnumMap<Edge, Edge>(Edge.class); static { opposites.put(TOP, BOTTOM); opposites.put(BOTTOM, TOP); opposites.put(LEFT, RIGHT); opposites.put(RIGHT, LEFT); } public Edge opposite(){ return opposites.get(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; } } 

随着Java 8 lambda:

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