Я просто узнал, что Java позволяет перечислениям реализовывать интерфейс. Каков был бы хороший вариант использования для этого?
Перечисления не должны просто представлять пассивные наборы (например, цвета). Они могут представлять более сложные объекты с функциональностью, и поэтому вы, вероятно, захотите добавить к ним дополнительные функции - например, у вас могут быть такие интерфейсы, как для печати
, для отчетов
и т. д., а также компоненты, которые их поддерживают.
Пример Comparable
, приведенный здесь несколькими людьми, неверен, поскольку Enum
уже реализует это. Вы даже не можете отменить это.
Лучшим примером является интерфейс, который определяет, скажем, тип данных. Вы можете иметь перечисление для реализации простых типов и обычные классы для реализации сложных типов:
interface DataType {
// methods here
}
enum SimpleDataType implements DataType {
INTEGER, STRING;
// implement methods
}
class IdentifierDataType implements DataType {
// implement interface and maybe add more specific methods
}
Вот один пример (похожий / лучший можно найти в Effective Java 2nd Edition):
public interface Operator {
int apply (int a, int b);
}
public enum SimpleOperators implements Operator {
PLUS {
int apply(int a, int b) { return a + b; }
},
MINUS {
int apply(int a, int b) { return a - b; }
};
}
public enum ComplexOperators implements Operator {
// can't think of an example right now :-/
}
Теперь, чтобы получить список обоих простых + сложных операторов:
List<Operator> operators = new ArrayList<Operator>();
operators.addAll(Arrays.asList(SimpleOperators.values()));
operators.addAll(Arrays.asList(ComplexOperators.values()));
Итак, здесь вы используете интерфейс для имитации расширяемых перечислений (что было бы невозможно без использования интерфейса).
Это требуется для расширяемости - если кто-то использует разработанный вами API, перечисления, которые вы определяете, являются статическими; они не могут быть добавлены или изменены. Однако, если вы позволите ему реализовать интерфейс, человек, использующий API, сможет разработать собственное перечисление, используя тот же интерфейс. Затем вы можете зарегистрировать это перечисление с помощью диспетчера перечислений, который объединяет перечисления вместе со стандартным интерфейсом.
Изменить: @Helper Method является прекрасным примером этого. Подумайте о том, чтобы другие библиотеки определяли новые операторы, а затем сообщали классу менеджера, что «эй, это перечисление существует - зарегистрируйте его». В противном случае вы могли бы определять операторы только в своем собственном коде - расширяемости не было бы.
Перечисления - это просто замаскированные классы, поэтому по большей части все, что вы можете делать с классом, вы можете делать с помощью перечисления.
Я не могу придумать причину, по которой перечисление не может реализовывать интерфейс, в то же время я не могу придумать вескую причину для них.
Я бы сказал, что как только вы начнете добавлять в перечисление такие вещи, как интерфейсы или методы, вам действительно стоит подумать о том, чтобы вместо этого сделать их классом. Конечно, я уверен, что есть допустимые случаи для выполнения нетрадиционных вещей enum, и, поскольку ограничение будет искусственным, я за то, чтобы люди могли там делать то, что они хотят.
Поскольку перечисления могут реализовывать интерфейсы, их можно использовать для строгого соблюдения одноэлементного шаблона. Попытка сделать стандартный класс синглтоном позволяет ...
Перечисления как синглтоны помочь предотвратить эти проблемы с безопасностью. Это могло быть одной из причин, по которым Enums могли действовать как классы и реализовывать интерфейсы. Просто догадка.
См. https://stackoverflow.com/questions/427902/java-enum-singleton и Класс Singleton в java для более подробного обсуждения.
Например, если у вас есть перечисление Logger. Затем у вас должны быть методы регистратора, такие как отладка, информация, предупреждение и ошибка в интерфейсе. Это делает ваш код слабосвязанным.