Illegal Forward Reference and Enums

前端 未结 11 1422
-上瘾入骨i
-上瘾入骨i 2020-12-08 09:46

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.

相关标签:
11条回答
  • 2020-12-08 10:05

    You can also make use of an static innerclass inside the enum:

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

    Stolen from here :)

    0 讨论(0)
  • 2020-12-08 10:09

    You could just define a method similar to the one below.

    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");
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-08 10:09

    My method is by using ordinal. This is a simple example, but for a much more complex example see below.

    public enum Edge {
        // Don't change the order! This class uses ordinal() in an arithmetic context.
        TOP,    // = 0
        LEFT,   // = 1
        RIGHT,  // = 2
        BOTTOM; // = 3
    
        public Edge other() {
            return values()[3 - ordinal()];
        }
    }
    

    Although using ordinal is discouraged for being fragile, using ordinal in the same enum as it's defined in is less fragile, and it's further mitigated here with a comment. Though the example above is quite trivial, the next example is less so. Compare the original way and the way using ordinal:

    From 98 lines:

    public enum Axes {
        NONE,
        HORIZONTAL,
        VERTICAL,
        BOTH;
    
        public Axes add(Axes axes) {
            switch (axes) {
                case HORIZONTAL:
                    if (this == NONE)
                        return HORIZONTAL;
                    if (this == VERTICAL)
                        return BOTH;
                    break;
                case VERTICAL:
                    if (this == NONE)
                        return VERTICAL;
                    if (this == HORIZONTAL)
                        return BOTH;
                    break;
                case BOTH:
                    return BOTH;
                default:
                    throw new AssertionError(axes);
            }
            return this;
        }
    
        public Axes remove(Axes axes) {
            switch (axes) {
                case HORIZONTAL:
                    if (this == HORIZONTAL)
                        return NONE;
                    if (this == BOTH)
                        return VERTICAL;
                    break;
                case VERTICAL:
                    if (this == VERTICAL)
                        return NONE;
                    if (this == BOTH)
                        return HORIZONTAL;
                    break;
                case BOTH:
                    return NONE;
                default:
                    throw new AssertionError(axes);
            }
            return this;
        }
    
        public Axes toggle(Axes axes) {
            switch (axes) {
                case NONE:
                    return this;
                case HORIZONTAL:
                    switch (this) {
                        case NONE:
                            return HORIZONTAL;
                        case HORIZONTAL:
                            return NONE;
                        case VERTICAL:
                            return BOTH;
                        case BOTH:
                            return VERTICAL;
                        default:
                            throw new AssertionError(axes);
                    }
                case VERTICAL:
                    switch (this) {
                        case NONE:
                            return VERTICAL;
                        case HORIZONTAL:
                            return BOTH;
                        case VERTICAL:
                            return NONE;
                        case BOTH:
                            return HORIZONTAL;
                        default:
                            throw new AssertionError(axes);
                    }
                case BOTH:
                    switch (this) {
                        case NONE:
                            return BOTH;
                        case HORIZONTAL:
                            return VERTICAL;
                        case VERTICAL:
                            return HORIZONTAL;
                        case BOTH:
                            return NONE;
                        default:
                            throw new AssertionError(axes);
                    }
                default:
                    throw new AssertionError(axes);
            }
        }
    }
    

    to 19 lines:

    public enum Axes {
        // Don't change the order! This class uses ordinal() as a 2-bit bitmask.
        NONE,       // = 0 = 0b00
        HORIZONTAL, // = 1 = 0b01
        VERTICAL,   // = 2 = 0b10
        BOTH;       // = 3 = 0b11
    
        public Axes add(Axes axes) {
            return values()[ordinal() | axes.ordinal()];
        }
    
        public Axes remove(Axes axes) {
            return values()[ordinal() & ~axes.ordinal()];
        }
    
        public Axes toggle(Axes axes) {
            return values()[ordinal() ^ axes.ordinal()];
        }
    }
    
    0 讨论(0)
  • 2020-12-08 10:12

    You could use an internal Map instead to define these associations. This works if at the point of initializing the Map, you already have all enum values created:

    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);
      }
    }
    
    0 讨论(0)
  • 2020-12-08 10:13
    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();
    }
    
    0 讨论(0)
提交回复
热议问题