Методы Перечисления Java


Я хотел бы объявить направление перечисления, которое имеет метод, который возвращает противоположное направление (следующее синтаксически неверно, т. е. перечисления не могут быть созданы, но это иллюстрирует мою точку зрения). Возможно ли это в Java?

вот код:

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);
     }
}
6 85

6 ответов:

для тех, кто заманил сюда по названию: да, вы можете определить свои собственные методы в enum. Если вам интересно, как вызвать такой нестатический метод, вы делаете это так же, как и с любым другим нестатическим методом-вы вызываете его на экземпляре типа, который определяет или наследует этот метод. В случае перечислений такие экземпляры просто ENUM_CONSTANT s.

так что все, что вам нужно, это EnumType.ENUM_CONSTANT.methodName(arguments).


теперь давайте вернемся к проблеме из вопроса. Одним из решений может быть

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

}

теперь Direction.NORTH.getOppositeDirection() вернутся Direction.SOUTH.


вот немного более "хаки" способ проиллюстрировать @jedwards комментарий но это не так гибко, как первый подход

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

    private static final Direction[] VALUES = values();//cached values 
                                                       //to avoid recreating array

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

для такого небольшого перечисления я нахожу наиболее читаемым решением:

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();

}

это работает:

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

создайте абстрактный метод, и пусть каждое из ваших значений перечисления переопределит его. Поскольку вы знаете противоположное, когда создаете его, нет необходимости динамически генерировать или создавать его.

это не читается хорошо, хотя; возможно, a switch было бы более управляемым?

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

Да мы делаем это все время. Вы возвращаете статический экземпляр, а не новый объект

 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;
 }
public enum Direction {
    NORTH, EAST, SOUTH, WEST;

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

перечисления имеют метод статических значений, который возвращает массив, содержащий все значения перечисления в порядке их объявления. источник

так как Север получает 1, Восток получает 2, юг получает 3, Запад получает 4; вы можете создать простое уравнение, чтобы получить противоположное:

(значение + 2) % 4