@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 |
---|---|
java.lang.Class |
code
If defined, all unimplemented methods will execute the code found within the supplied closure.
|
java.lang.Class<? extends java.lang.RuntimeException> |
exception
If defined, all unimplemented methods will throw this exception.
|
java.lang.String |
message
If
exception is defined, message can be used to specify the exception message. |
public abstract java.lang.Class<? extends java.lang.RuntimeException> exception
code
is defined.