簡體   English   中英

是否可以在Groovy中為其自己的類型提供Enums實例變量?

[英]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及其方向。 當我在某個DirectionRoom添加到另一個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
}

其中connectionspublic 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
    }
}

但我發現第一個更清晰,因為它不需要索引的那些神奇數字呵呵。

更新2

現在,我可能會在這里進入高爾夫球場,但是你可以在不需要額外場的情況下獲得相反的方向,只需使用枚舉值' 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM