[英]Is it possible to give Enums instance variables of their own type in Groovy?
我在Groovy中制作一個Text Adventure游戲作為一種練習,我遇到了一個奇怪的錯誤。
現在,我有一個關於玩家可以前往的方向的enum
,目前包含North,South,East,West,Up和Down。
我有一個Room
類,其中包含其他連通房間的Map
及其方向。 當我在某個Direction
將Room
添加到另一個Room
時,我希望能夠將當前Room
添加到相反方向的另一個Room
。
例如:如果我將房間1到房間2的連接添加到北方,我希望能夠同時從房間2到房間1添加連接。
目前,我想實現這個使用enum
命名的Direction
與連接實例變量opposite
(類型Direction
)。 這是不允許的? 我沒有得到編譯器錯誤或任何東西,但我似乎無法讓它工作。
這是完整的enum
聲明:
public enum Direction {
North(South), South(North), East(West), West(East), Up(Down), Down(Up)
private Direction opposite
Direction(Direction d){
opposite = d
}
public opposite(){
return opposite
}
}
這是我從以下方法調用它的方法:
public void addConnection(Direction d, Spot spot){
connections[d] = spot
spot.connections[d.opposite()] = this
}
其中connections
是public Map<Direction, Spot>
。
在這種情況下,條目將添加到如下所示的connections
:
null:Spot@some_hexadecimal_representation
任何幫助都會很棒。 謝謝!
Groovy似乎繞過Java中的編譯錯誤 :
Main.java:2: illegal forward reference
North(South), South(North), East(West), West(East), Up(Down), Down(Up);
^
Main.java:2: illegal forward reference
North(South), South(North), East(West), West(East), Up(Down), Down(Up);
^
Main.java:2: illegal forward reference
North(South), South(North), East(West), West(East), Up(Down), Down(Up);
^
3 errors
groovy編譯器沒有抱怨,但是將需要前向聲明的枚舉值初始化為null
:
public enum Direction {
North(South), South(North), East(West), West(East), Up(Down), Down(Up)
Direction(Direction d){
println "opposite of $this is $d"
}
}
Direction.South // Force enum instantiation in GroovyConsole.
產出 :
opposite of North is null
opposite of South is North
opposite of East is null
opposite of West is East
opposite of Up is null
opposite of Down is Up
一個似乎在Java中運行良好的解決方案是在Direction
類上添加一個static
塊來初始化opposite
值。 轉換為Groovy,即:
enum Direction {
North, South, East, West, Up, Down
private Direction opposite
Direction getOpposite() { opposite }
static {
def opposites = { d1, d2 -> d1.opposite = d2; d2.opposite = d1 }
opposites(North, South)
opposites(East, West)
opposites(Up, Down)
}
}
Direction.values().each {
println "opposite of $it is $it.opposite"
}
現在打印正確的值 :
opposite of North is South
opposite of South is North
opposite of East is West
opposite of West is East
opposite of Up is Down
opposite of Down is Up
另一個可能更簡單的解決方案是使用枚舉上的方向索引來查找對立面:
public enum Direction {
North(1), South(0), East(3), West(2), Up(5), Down(4)
private oppositeIndex
Direction getOpposite() {
values()[oppositeIndex]
}
Direction(oppositeIndex) {
this.oppositeIndex = oppositeIndex
}
}
但我發現第一個更清晰,因為它不需要索引的那些神奇數字呵呵。
現在,我可能會在這里進入高爾夫球場,但是你可以在不需要額外場的情況下獲得相反的方向,只需使用枚舉值' ordinal()
(它們的索引):
enum Direction {
North, South, East, West, Up, Down
Direction getOpposite() {
values()[ordinal() + ordinal() % 2 * -2 + 1]
}
}
它並不像它看起來那么可怕! 偶數方向(北,東,上)返回ordinal() + 1
的方向作為相反方向,而奇數方向(其他方向)返回ordinal() - 1
。 當然,它在很大程度上依賴於枚舉中元素的順序,但是,你不喜歡簡潔嗎? = d
您可以通過將其傳遞給閉包並在需要相反時調用閉包來推遲對相反的評估:
public enum Direction {
North({South}), South({North}), East({West}), West({East}), Up({Down}), Down({Up})
private def opp
Direction(opp) {
this.opp = opp
}
public opposite() {
return opp()
}
}
public static void main(String[] args) {
Direction.each { d ->
println "${d} ... ${d.opposite()}"
}
}
輸出:
North ... South South ... North East ... West West ... East Up ... Down Down ... Up
看起來,當調用枚舉構造函數時,一半的Directions
未初始化。 也就是說,當您呼叫North(South)
,南尚未初始化。 這是下一個。
你遇到了雞/蛋悖論,其中所有的枚舉常數必須在其中一個之前初始化。 您似乎需要重新組織一些代碼來解決這個問題。 我可能會建議:
public enum Direction {
North(1), South(~1), East(2), West(~2), Up(4), Down(~4);
private int value;
Direction(int d){
value = d;
}
private int getValue() {
return value;
}
public Direction opposite(){
for (Direction d : Direction.values()) {
if (value == ~(d.getValue()))
return d;
}
return null;
}
}
這利用了按位運算符~
來區分對立面。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.