Java Enum Methods - return opposite direction enum

JavaEnumsEnumeration

Java Problem Overview


I would like to declare an enum Direction, that has a method that returns the opposite direction (the following is not syntactically correct, i.e, enums cannot be instantiated, but it illustrates my point). Is this possible in Java?

Here is the code:

public enum Direction {

     NORTH(1),
     SOUTH(-1),
     EAST(-2),
     WEST(2);

     Direction(int code){
          this.code=code;
     }
     protected int code;
     public int getCode() {
           return this.code;
     }
     static Direction getOppositeDirection(Direction d){
           return new Direction(d.getCode() * -1);
     }
}

Java Solutions


Solution 1 - Java

For those lured here by title: yes, you can define your own methods in your enum. If you are wondering how to invoke such non-static method, you do it same way as with any other non-static method - you invoke it on instance of type which defines or inherits that method. In case of enums such instances are simply ENUM_CONSTANTs.

So all you need is EnumType.ENUM_CONSTANT.methodName(arguments).


Now lets go back to problem from question. One of solutions could be

public enum Direction {
    
    NORTH, SOUTH, EAST, WEST;
    
    private Direction opposite;
    
    static {
    	NORTH.opposite = SOUTH;
    	SOUTH.opposite = NORTH;
    	EAST.opposite = WEST;
    	WEST.opposite = EAST;
    }
    
    public Direction getOppositeDirection() {
    	return opposite;
    }
        
}

Now Direction.NORTH.getOppositeDirection() will return Direction.SOUTH.


Here is little more "hacky" way to illustrate @jedwards comment but it doesn't feel as flexible as first approach since adding more fields or changing their order will break our code.

public enum Direction {
	NORTH, EAST, SOUTH, WEST;
	
    // cached values to avoid recreating such array each time method is called
    private static final Direction[] VALUES = values();

	public Direction getOppositeDirection() {
		return VALUES[(ordinal() + 2) % 4]; 
	}
}

Solution 2 - Java

For a small enum like this, I find the most readable solution to be:

public enum Direction {

    NORTH {
        @Override
        public Direction getOppositeDirection() {
            return SOUTH;
        }
    }, 
    SOUTH {
        @Override
        public Direction getOppositeDirection() {
            return NORTH;
        }
    },
    EAST {
        @Override
        public Direction getOppositeDirection() {
            return WEST;
        }
    },
    WEST {
        @Override
        public Direction getOppositeDirection() {
            return EAST;
        }
    };


    public abstract Direction getOppositeDirection();

}

Solution 3 - Java

This works:

public enum Direction {
	NORTH, SOUTH, EAST, WEST;

	public Direction oppose() {
		switch(this) {
			case NORTH: return SOUTH;
			case SOUTH: return NORTH;
			case EAST:  return WEST;
			case WEST:  return EAST;
		}
		throw new RuntimeException("Case not implemented");
	}
}

Solution 4 - Java

Create an abstract method, and have each of your enumeration values override it. Since you know the opposite while you're creating it, there's no need to dynamically generate or create it.

It doesn't read nicely though; perhaps a switch would be more manageable?

public enum Direction {
    NORTH(1) {
        @Override
        public Direction getOppositeDirection() {
            return Direction.SOUTH;
        }
    },
    SOUTH(-1) {
        @Override
        public Direction getOppositeDirection() {
            return Direction.NORTH;
        }
    },
    EAST(-2) {
        @Override
        public Direction getOppositeDirection() {
            return Direction.WEST;
        }
    },
    WEST(2) {
        @Override
        public Direction getOppositeDirection() {
            return Direction.EAST;
        }
    };

    Direction(int code){
        this.code=code;
    }
    protected int code;
    
    public int getCode() {
        return this.code;
    }

    public abstract Direction getOppositeDirection();
}

Solution 5 - Java

Yes we do it all the time. You return a static instance rather than a new Object

 static Direction getOppositeDirection(Direction d){
       Direction result = null;
       if (d != null){
           int newCode = -d.getCode();
           for (Direction direction : Direction.values()){
               if (d.getCode() == newCode){
                   result = direction;
               }
           }
       }
       return result;
 }

Solution 6 - Java

public enum Direction {
    NORTH, EAST, SOUTH, WEST;

    public Direction getOppositeDirection(){
        return Direction.values()[(this.ordinal() + 2) % 4];
    }
}

Enums have a static values method that returns an array containing all of the values of the enum in the order they are declared. source

since NORTH gets 1, EAST gets 2, SOUTH gets 3, WEST gets 4; you can create a simple equation to get the opposite one:

(value + 2) % 4

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSkylerView Question on Stackoverflow
Solution 1 - JavaPshemoView Answer on Stackoverflow
Solution 2 - JavaAmir AfghaniView Answer on Stackoverflow
Solution 3 - JavaPikrassView Answer on Stackoverflow
Solution 4 - JavaMakotoView Answer on Stackoverflow
Solution 5 - JavaBevynQView Answer on Stackoverflow
Solution 6 - JavaPreguntonView Answer on Stackoverflow