Оригинал тут: Turning Java enums into Groovy ranges
Предположим что у нас есть простой Java Enum:
[java]
public enum Season {
WINTER, SPRING, SUMMER, FALL
}
[/java]
Так как enum-ы реализуют интерфейс Comparable, то в них есть метод compareTo().
Тем не менее их значения нельзя использовать с операторами < и >.
Потому такой Java-код даже не скомпилируется
[java]if (Season.WINTER > Season.FALL) { … }[/java]
Напротив, в Groovy же, для любого класса, который реализует Comparable можно использовать операторы < и >. Потому такой Groovy-код, работает как и ожидается:
[java]assert Season.FALL > Season.WINTER[/java]
Так как enum уже реализует Comparable, то для того, чтоб превратить его в Groovy Range, осталось добавить только методы next() и previous().
Вот один из способов сделать это, используя метод ordinal() enum-а:
[java]
public enum Season {
WINTER, SPRING, SUMMER, FALL;
Season next() {
Season[] vals = Season.values();
return vals[(this.ordinal() + 1) % vals.length];
}
Season previous() {
Season[] vals = Season.values();
return vals[(this.ordinal() - 1 + vals.length) % vals.length];
}
}
[/java]
Теперь в Groovy можно написать так:
[java]
(Season.WINTER..Season.FALL).each {
println it
}
// ...
for (s in Season.values()) {
println (s++)
}
// ...
for (s in Season.values()) {
println (s--)
}
[/java]
Налицо использование, принятой в Groovy, концепции Duck Typing, когда нас не обязуют декларировать реализацию интерфейся для использования с языковыми операторами (в данном случае “больше-меньше”). Достаточно только реализовать необходимые методы, без указания какого-либо дополнительного implements в сигнатуре класса.
Кстати в Java есть метод EnumSet.range(), который возвращает коллекцию значений enum-а, которая в свою очередь может быть использована в Java5 for-each цикле:
[java]for (Season s : EnumSet.range(Season.WINTER, Season.FALL) { … }[/java]
Но в в таком случае использование операторов < и > все равно не допускается.