Enum Initialization Error

Fun… I am asking a noob question in java :open_mouth: :slight_smile:

It’s about Enums, I started using them recently. I have a problem with this code:


	protected static enum Side {
		LEFT("BOTTOM", "TOP"),
		TOP("LEFT", "RIGHT"),
		RIGHT("TOP", "BOTTOM"),
		BOTTOM("RIGHT", "LEFT");

		public final Side toLeft;
		public final Side toRight;

		Side(String l, String r) {
			toLeft = Side.valueOf(l);
			toRight = Side.valueOf(r);
		}
	}

(Inner-Class-Enum)

I want to store the references to the sides of each side. So the neighbour of top is left to the left and right to the right…

The sides look like this:
......TOP....... .L............R. .E............I. .F............G. .T............H. ..............T. .....BOTTOM.....
How would you solve this problem?

You can’t do what you just tried. There are several options though as to how. None of them will probably be what you want, but it’s the way that they work. Especially if you want to include the ‘final’ functionality.

Best way around it? Create an initializer method that you call where-ever other things get initialized to set up these relations. Then get them through a method (Which causes these variables to act as final for this purpose, since an enum cannot be extended.)


protected static enum Side {
    LEFT, TOP, RIGHT, BOTTOM;
    public static void initialize() {
        LEFT.toLeft = BOTTOM;
        LEFT.toRight = TOP;
        // Etc.
    }
    private Side toLeft;
    private Side toRight;

    public Side getToLeft() {
        return toLeft;
    }

    public Side getToRight() {
        return toRight;
    }
}

I am guessing that the problem comes from the fact that the method you are calling assumes to have a reference to all the other enum constants. Since it’s used in the constructor, the references it needs do not exist yet.

Here is one alternative. You could also use a switch statement with enum consant values or an enum map.


  public enum Side
  {
    Left { public Side cw() { return Top; } public Side ccw() { return Bottom; } },
    Top { public Side cw() { return Right; } public Side ccw() { return Left; } },
    Right { public Side cw() { return Bottom; } public Side ccw() { return Top; } },
    Bottom { public Side cw() { return Left; } public Side ccw() { return Right; } };

    public abstract Side cw();
    public abstract Side ccw();
  }

Edit: UprightPath submitted something while I was still writing, but the only change I made was to correct a spelling error.

and another possibility


public enum Side
{
  TOP, RIGHT, BOTTOM, LEFT;//Note that the sides are in clockwise order
  
  public Side getClockWise()
  {
    return values()[(ordinal()+1)%4];
  }
  
  public Side getCounterClockWise()
  {
    return values()[Math.abs((ordinal()-1)%4)];
  }
}

ps: one could ofcourse also hardcode the to idices per side

You can use a static initializer to keep the entire definition within the enum and retrieve without having to recalculate anything each time. I made toLeft and toRight private and added accessor methods. They are no longer final but you can’t change the values any how.


enum Side {
	
	
    LEFT,
    TOP,
    RIGHT,
    BOTTOM;

    private  Side toLeft;
    private  Side toRight;
    
    private void setSides(Side leftSide, Side rightSide) {
    	toLeft = leftSide;
    	toRight = rightSide;
    }
    
    public Side left() {
    	return toLeft;
    }
    
    public Side right() {
    	return toRight;
    }


    static {
    	
    	LEFT.setSides(BOTTOM,TOP);
    	RIGHT.setSides(TOP, BOTTOM);
    	TOP.setSides(LEFT,RIGHT);
    	BOTTOM.setSides(RIGHT,LEFT);
    }
}



then



		System.out.println(Side.LEFT.left() == Side.RIGHT);  // prints false
		System.out.println(Side.LEFT.left() == Side.BOTTOM);  // prints true


Eclipse complained when I tried making the enum static and protected.

ah yes sry^^
quite interesting how many different implementations are possible for this simple problem :slight_smile:

Yes it is. I would also be tempted to add something like :


    public static Side leftOf(Side side) {
    	return side.toLeft;
    }
    
    public static Side rightOf(Side side) {
    	return side.toRight;
    }

So I could do things like:



Side neighbor = Side.leftOf(enemy.facingDirection());


which reads more naturally to me (although that’s just preference).

Yes… I have many to choose from ;D
I think I’ll choose yours, because it’s the most beautiful in my eyes :slight_smile:

It’s nested :slight_smile:

You like it? then another one, perhaps even more elegant :slight_smile:

UPDATED:


public enum Direction
{
  Front, Right, Back, Left; 

  public Direction get(Direction d)
  {
    return values()[(d.ordinal() + ordinal()) % 4];
  }
}

So you can write entityDirection.get(Back) to get the Direction which is in the opposit direction of the entity or entDir.get(Left) the dir which is left …

I’ve never been a fan of the static code chunk, if only because it’s hard to tell when it gets executed. For this, I figure it’s not too much of a problem, but I tend to not suggest it. xD

Matheus, Danny,

While the code is nice and compact, in this specific case, I think doing something more like:


enum Side {
   
    LEFT, TOP,  RIGHT,  BOTTOM;

    public Side left() {
       return toLeft;
    }
    
    public Side right() {
       return toRight;
    }

    public Side opposite() {
      return oppositeOf;
   }

    private Side toLeft, toRight, oppositeOf;
    
    private void setSides(Side leftSide, Side rightSide, Side oppositeSide) {
       toLeft = leftSide;
       toRight = rightSide;
       oppositeOf = oppositeSide;
    }

    static {
       LEFT.setSides(BOTTOM,TOP,RIGHT);
       RIGHT.setSides(TOP, BOTTOM,LEFT);
       TOP.setSides(LEFT,RIGHT,BOTTOM);
       BOTTOM.setSides(RIGHT,LEFT,TOP);
    }
}

is simpler in that you don’t have to care about the order the Enum values are defined in and you don’t have to do calculations, array lookups, or retrieving ordinal positions to get what can be defined simply once and for all. The downside is storing 3 enum values for each enum which in this case is nothing. If the Enum had a lot more values (N,NNE,NE,ENE,E, etc…) or had a lot more relationships to track then the more compact code would look more attractive.

[quote]I’ve never been a fan of the static code chunk, if only because it’s hard to tell when it gets executed. For this, I figure it’s not too much of a problem, but I tend to not suggest it. xD
[/quote]
I got the static initializer idea from a stack overflow post. I was originally thinking along your lines but what I like about this is that the definition is complete within itself. You don’t have to remember to call a method from some where else. Then again, I tend to use statics more often than other Java programmers I’ve worked with.

You guys are VERY fun :slight_smile: I like this community :smiley:

Even if It’s not about entities (It’s about planet “sides”), this has helped me a lot :slight_smile: thank you!