@Documented @Retention(value=SOURCE) @Target(value=TYPE) public @interface AutoImplement
Example usage:
import groovy.transform.AutoImplementIn the above example, since@AutoImplement
class EmptyStringIterator implements Iterator{ boolean hasNext() { false } } assert !new EmptyStringIterator().hasNext()
hasNext
returns false, the next
method
should never be called, so any dummy implementation would do for next
.
The "empty" implementation provided by default when using @AutoImplement
will suffice - which effectively returns null
in Groovy for non-void,
non-primitive methods.
As a point of interest, the default implementation for methods returning primitive
types is to return the default value (which incidentally never satisfies Groovy truth).
For boolean
this means returning false
, so for the above example we
could have (albeit perhaps less instructive of our intent) by just using:
If we didn't want to assume that callers of our@AutoImplement
class EmptyStringIterator implements Iterator{ }
EmptyStringIterator
correctly followed
the Iterator
contract, then we might want to guard against inappropriate calls to next
.
Rather than just returning null
, we might want to throw an exception. This is easily done using
the exception
annotation attribute as shown below:
import groovy.transform.AutoImplement import static groovy.test.GroovyAssert.shouldFailAll implemented methods will throw an instance of this exception constructed using its no-arg constructor. You can also supply a single@AutoImplement
(exception=UnsupportedOperationException) class EmptyStringIterator implements Iterator{ boolean hasNext() { false } } shouldFail(UnsupportedOperationException) { new EmptyStringIterator().next() }
message
annotation attribute in which case the message will be passed
as an argument during exception construction as shown in the following example:
Finally, you can alternatively supply a@AutoImplement
(exception=UnsupportedOperationException, message='Not supported for this empty iterator') class EmptyStringIterator implements Iterator{ boolean hasNext() { false } } def ex = shouldFail(UnsupportedOperationException) { new EmptyStringIterator().next() } assert ex.message == 'Not supported for this empty iterator'
code
annotation attribute in which case a closure
block can be supplied which should contain the code to execute for all implemented methods. This can be
seen in the following example:
@AutoImplement
(code = { throw new UnsupportedOperationException("Not supported for ${getClass().simpleName}") }) class EmptyStringIterator implements Iterator{ boolean hasNext() { false } } def ex = shouldFail(UnsupportedOperationException) { new EmptyStringIterator().next() } assert ex.message == 'Not supported for EmptyStringIterator'
Modifier and Type | Optional Element and Description |
---|---|
Class |
code
If defined, all unimplemented methods will execute the code found within the supplied closure.
|
Class<? extends RuntimeException> |
exception
If defined, all unimplemented methods will throw this exception.
|
String |
message
If
exception is defined, message can be used to specify the exception message. |
public abstract Class<? extends RuntimeException> exception
code
is defined.public abstract String message
exception
is defined, message
can be used to specify the exception message.
Will be ignored if code
is defined or exception
isn't defined.public abstract Class code