Categories and Extension Modules
Prerequisites: Runtime metaprogramming
Two safer ways to add methods to existing classes.
Categories — methods in a scope
A category is a class of static methods. Inside a use block, the
first parameter becomes the receiver:
class StringExtras {
static String slugify(String self) {
self.toLowerCase().replaceAll(/[^a-z0-9]+/, '-').replaceAll(/^-|-$/, '')
}
static int wordCount(String self) { self.tokenize().size() }
}
use(StringExtras) {
println 'Hello, Groovy World!'.slugify()
println 'one two three'.wordCount()
}
try {
'outside'.slugify()
} catch (MissingMethodException e) {
println 'slugify() only exists inside use { }'
}
hello-groovy-world
3
slugify() only exists inside use { }
Changes are visible only inside the use block (and only on that
thread), so they can't leak into other code.
TimeCategory
Groovy ships a category for readable durations and dates:
import groovy.time.TimeCategory
use(TimeCategory) {
def meeting = 1.hour + 30.minutes
println meeting
println 90.minutes
def start = Date.parse('yyyy-MM-dd HH:mm', '2026-09-29 09:00')
println((start + 2.days + 3.hours).format('yyyy-MM-dd HH:mm'))
}
1 hours, 30 minutes
90 minutes
2026-10-01 12:00
Extension modules — permanent additions, done properly
An extension module is how Groovy itself adds methods to JDK classes, and how libraries ship their own. You write static methods in a normal class and register them in a descriptor file on the classpath:
// illustrative — src/main/groovy/com/example/MoneyExtension.groovy
package com.example
class MoneyExtension {
static BigDecimal withVat(BigDecimal self, BigDecimal rate = 0.2) {
self * (1 + rate)
}
static String asEuro(Number self) {
String.format(Locale.UK, '€%,.2f', self)
}
}
# src/main/resources/META-INF/groovy/org.codehaus.groovy.runtime.ExtensionModule
moduleName=money-extensions
moduleVersion=1.0
extensionClasses=com.example.MoneyExtension
Once the jar is on the classpath, every Groovy script and class can call
100.0.withVat() or 1234.5.asEuro() — and, unlike metaclass
changes, extension methods are also seen by @CompileStatic code and
by IDEs.
Choosing a technique
| Technique | Scope | Static compilation | Typical use |
|---|---|---|---|
metaClass |
global, runtime | no | scripts, tests, frameworks |
Category (use) |
a block, one thread | no | temporary DSL vocabulary |
| Extension module | everywhere the jar is | yes | libraries, team utilities |
| Trait | classes that implement it | yes | your own types |