Categories allow us to add extra functionality to classes, even those classes we didn't develop ourselves. A Category class contain static methods. The first argument of the method determines the type the method can be applied to.
We can also use the @Category transformation annotation to make a class into a Category. The class doesn't have to define static methods anymore, but we can use instance methods. The parameter of the @Category annotation defines for which class the Category is.
The Category can be applied to a specific code block with the use keyword. Only within the code block the rules of the Category are applied.
class Speak {
static String shout(String text) { // Method argument is String, so we can add shout() to String object.
text.toUpperCase() + '!'
}
static String whisper(String text, boolean veryQuiet = false) {
"${veryQuiet ? 'sssssssh' : 'sssh'}.. $text"
}
static String army(String text) {
"$text. Sir, yes sir!"
}
}
use (Speak) {
assert 'PAY ATTENTION!' == "Pay attention".shout()
assert 'sssh.. Be vewy, vewy, quiet.' == "Be vewy, vewy, quiet.".whisper()
assert 'sssssssh.. Be vewy, vewy, quiet.' == "Be vewy, vewy, quiet.".whisper(true)
assert 'Groovy rocks. Sir, yes sir!' == "Groovy rocks".army()
}
// Or we can use the @Category annotation.
@Category(String)
class StreetTalk {
String hiphop() {
"Yo, yo, here we go. ${this}"
}
}
use(StreetTalk) {
assert 'Yo, yo, here we go. Groovy is fun!' == 'Groovy is fun!'.hiphop()
}
// We can use static methods from other Java classes.
use (org.apache.commons.codec.digest.DigestUtils) {
assert '900150983cd24fb0d6963f7d28e17f72' == 'abc'.md5Hex()
}