It turns out that it’s easy to turn a Java enum
into a type that can be used in a Groovy range.
Consider a simple enum
representing the seasons:
public enum Season {
WINTER, SPRING, SUMMER FALL
}
Since enums implement the Comparable
interface, they have a compareTo()
method. Despite that, however, you can’t use an enum with < or > in Java.
// Won't compile in Java
// if (Season.WINTER > Season.FALL) { ... }
In Groovy, though, any class that implements Comparable
can be used with < and >:
// Groovy version
assert Season.FALL > Season.WINTER
That works just fine.
Since the enum already implements Comparable
, turning it into a Groovy range simply requires adding in a next()
and a previous()
method. Here’s one way to do that, relying on the ordinal()
method in enum
, which returns the index of the enum
in the overall collection.
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];
}
}
Now in Groovy you can write:
(Season.WINTER..Season.FALL).each {
println it
}
or even
for (s in Season.values()) {
println (s++)
}
for (s in Season.values()) {
println (s--)
}
To be honest, I’m not sure where I’m ever going to use that capability, but it’s interesting.
(In Java, the EnumSet.range()
method returns a collection that can be used in the Java 5 for-each loop:
for (Season s : EnumSet.range(Season.WINTER, Season.FALL) { ... }
but you still can’t use the < or > operators. And the Groovy approach is still simpler.)
Leave a Reply