是否可以在Groovy中为其自己的类型提供Enums实例变量?

Ben*_*ach 8 java groovy enums

我在Groovy中制作一个Text Adventure游戏作为一种练习,我遇到了一个奇怪的错误.

现在,我有enum一个玩家能够前往的方向,目前包含北,南,东,西,上和下.

我有一个Room课程,其中包含Map其他连通房间及其方向.当我在某个时候添加Room到另一个RoomDirection,我希望能够在相反的方向上将电流添加Room到另一个.Room

例如:如果我将房间1到房间2的连接添加到北方,我希望能够同时从房间2到房间1添加连接.

目前,我正在尝试使用带有附加实例变量(类型)的enum命名来实现它.这是不允许的?我没有得到编译器错误或任何东西,但我似乎无法让它工作.DirectionoppositeDirection

这是完整的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
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我从以下方法调用它的方法:

public void addConnection(Direction d, Spot spot){
    connections[d] = spot
    spot.connections[d.opposite()] = this
}
Run Code Online (Sandbox Code Playgroud)

这里connections是一个public Map<Direction, Spot>.

在这种情况下,会添加一个条目connections,如下所示:

null:Spot@some_hexadecimal_representation
Run Code Online (Sandbox Code Playgroud)

任何帮助都会很棒.谢谢!

epi*_*ian 8

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
Run Code Online (Sandbox Code Playgroud)

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.
Run Code Online (Sandbox Code Playgroud)

产出:

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
Run Code Online (Sandbox Code Playgroud)

一个似乎在Java中运行良好的解决方案是添加一个staticDirection来初始化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"
}
Run Code Online (Sandbox Code Playgroud)

现在打印正确的值:

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
Run Code Online (Sandbox Code Playgroud)

更新

另一个可能更简单的解决方案是使用枚举上的方向索引来查找对立面:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

但我发现第一个更清晰,因为它不需要索引的那些神奇数字呵呵.

更新2

现在,我可能会在这里进入高尔夫球场,但是你可以在不需要额外场的情况下获得相反的方向,只需使用枚举值' ordinal()(它们的索引):

enum Direction {
    North, South, East, West, Up, Down
    Direction getOpposite() { 
        values()[ordinal() + ordinal() % 2 * -2 + 1]
    }
}
Run Code Online (Sandbox Code Playgroud)

它并不像它看起来那么可怕!偶数方向(北,东,上)返回方向ordinal() + 1为相反方向,而奇数方向(其他方向)则返回方向ordinal() - 1.当然,它在很大程度上依赖于枚举中元素的顺序,但是,你不喜欢简洁吗?= d

  • @BenjaminKovach如果你不想要太多的可读性(或者你想为代码的未来维护者留下一些谜语),请看看我对答案的第二次更新 xD (2认同)
  • +1尼斯解决方案!您也可以用`@Lazy opposite = {values()[ordinal()+ ordinal()%2*-2 + 1]}()`替换`getOpposite`方法,如果你只想计算一次(虽然在这种情况下,它是矫枉过正的);-) (2认同)