Groovy supports the @Delegate annotation. With this annotation we can import all the methods of the class the annotation is used for. For example if we use the delegate annotation for the Date
class we get all the methods of the Date
class in our class. Just like that. This is best explained with a little sample in which we use the @Delegate annotation for properties of type Date
and List
:
class SimpleEvent { @Delegate Date when @Delegate List<String> attendees = [] int maxAttendees = 0 String description } def event = new SimpleEvent(when: new Date() + 7, description: 'Small Groovy seminar', maxAttendees: 2) assert 0 == event.size() // Delegate to List.size() assert event.after(new Date()) // Delegate to Date.after() assert 'Small Groovy seminar' == event.description assert 2 == event.maxAttendees event << 'mrhaki' << 'student1' // Delegate to List.leftShift() assert 2 == event.size() assert 'mrhaki' == event[0] event -= 'student1' // Delegate to List.minus() assert 1 == event.size()
We have used the @Delegate annotations and as by magic the SimpleEvent
has all methods of both the Date
class and List
interface. The code reads naturally and the meaning is obvious. Because the SimpleEvent
class has all methods from the List
interface we can override the methods as well. In our sample we override the add()
so we can check if the number of attendees doesn't exceed the maximum number of attendees allowed:
class SimpleEvent { @Delegate Date when @Delegate List<String> attendees = [] int maxAttendees = 0 String description boolean add(Object value) { if (attendees.size() < maxAttendees) { return attendees.add(value) } else { throw new IllegalArgumentException("Maximum of ${maxAttendees} attendees exceeded.") } } } def event = new SimpleEvent(when: new Date() + 7, description: 'Small Groovy seminar', maxAttendees: 2) event << 'mrhaki' << 'student1' try { event << 'three is a crowd.' assert false } catch (IllegalArgumentException e) { assert 'Maximum of 2 attendees exceeded.' == e.message }