Annotation Type Delegate
-
@Documented @Retention(RUNTIME) @Target({FIELD,METHOD}) public @interface DelegateAnnotation to automatically delegate part of the functionality of an owner class to the annotated delegation target. The target can be a field (or property) or a method's return value.The delegate type is either the type of the annotated field (or property) or the return type of the annotated method. The method can be thought of as a getter or factory method for the delegate. All public instance methods present in the delegate type and not present in the owner class will be added to owner class at compile time. The implementation of such automatically added methods is code which calls through to the delegate as per the normal delegate pattern.
As an example, consider this code:
class Event {In this example, the@DelegateDate when String title, url } def gr8conf = new Event(title: "GR8 Conference", url: "http://www.gr8conf.org", when: Date.parse("yyyy/MM/dd", "2009/05/18")) def javaOne = new Event(title: "JavaOne", url: "http://java.sun.com/javaone/", when: Date.parse("yyyy/MM/dd", "2009/06/02")) assert gr8conf.before(javaOne.when)Eventclass will have a method calledbefore(Date otherDate)as well as other public methods of theDateclass. The implementation of thebefore()method will look like this:public boolean before(Date otherDate) { return when.before(otherDate); }By default, the owner class will also be modified to implement any interfaces implemented by the delegate type. So, in the example above, becauseDateimplementsCloneablethe following will be true:assert gr8conf instanceof Cloneable
This behavior can be disabled by setting the annotation'sinterfaceselement to false, i.e.@Delegate(interfaces = false), e.g. in the above example, the delegate definition would become:and the following would be true:@Delegate(interfaces = false) Date whenassert !(gr8conf instanceof Cloneable)
If multiple delegation targets are used and the same method signature occurs in more than one of the respective delegate types, then the delegate will be made to the first defined target having that signature. If this does occur, it might be regarded as a smell (or at least poor style) and it might be clearer to do the delegation by long hand.By default, methods of the delegate type marked as
@Deprecatedare not automatically added to the owner class (but see the technical note about interfaces below). You can force these methods to be added by setting the annotation'sdeprecatedelement to true, i.e.@Delegate(deprecated = true).For example, in the example above if we change the delegate definition to:
then the following additional lines will execute successfully (during 2009):@Delegate(deprecated = true) Date whenassert gr8conf.year + 1900 == 2009 assert gr8conf.toGMTString().contains(" 2009 ")Otherwise these lines produce a groovy.lang.MissingPropertyException or groovy.lang.MissingMethodException respectively as those two methods are@DeprecatedinDate.Technical notes:
- Static methods, synthetic methods or methods from the
GroovyObjectinterface are not candidates for delegation - Non-abstract non-static methods defined in the owner class or its superclasses take
precedence over methods with identical signatures from a
@Delegatetarget - All methods defined in the owner class (including static, abstract or private etc.)
take precedence over methods with identical signatures from a
@Delegatetarget - Recursive delegation to your own class is not allowed
- Mixing of
@Delegatewith default method arguments is known not to work in some cases. We recommend not using these features together. - When the delegate type is an interface, the
deprecatedattribute will be ignored if the owner class implements that interface (i.e. you must setinterfaces=falseif you want thedeprecatedattribute to be used). Otherwise, the resulting class would not compile anyway without manually adding in any deprecated methods in the interface. @Delegatecan work in combination with@Lazywhen annotating a field (or property)
- Static methods, synthetic methods or methods from the
-
-
Optional Element Summary
Optional Elements Modifier and Type Optional Element Description booleanallNamesWhether to apply the delegate pattern to all methods, including those with names that are considered internal.booleandeprecatedWhether to apply the delegate pattern to deprecated methods; to avoid compilation errors, this is ignored if the type of the delegate target is an interface andinterfaces=true.java.lang.String[]excludesList of method and/or property names to exclude when delegating.java.lang.Class[]excludeTypesList of interfaces containing method signatures to exclude when delegating.java.lang.String[]includesList of method and/or property names to include when delegating.java.lang.Class[]includeTypesList of interfaces containing method signatures to include when delegating.booleaninterfacesbooleanmethodAnnotationsWhether to carry over annotations from the methods of the delegate to your delegating method.booleanparameterAnnotationsWhether to carry over annotations from the parameters of delegate methods to your delegating method.
-
-
-
-
deprecated
boolean deprecated
Whether to apply the delegate pattern to deprecated methods; to avoid compilation errors, this is ignored if the type of the delegate target is an interface andinterfaces=true.- Returns:
- true if owner class should delegate to methods annotated with @Deprecated
- Default:
- false
-
-
-
excludes
java.lang.String[] excludes
List of method and/or property names to exclude when delegating. Only one of 'includes', 'includeTypes', 'excludes' or 'excludeTypes' should be used. For convenience, a String with comma separated names can be used in addition to an array (using Groovy's literal list notation) of String values. If interfaces is true (the default), you will need to manually supply any methods excluded from delegation that are required for the interface.- Since:
- 2.2.0
- Default:
- {}
-
-
-
excludeTypes
java.lang.Class[] excludeTypes
List of interfaces containing method signatures to exclude when delegating. Only one of 'includes', 'includeTypes', 'excludes', 'excludeTypes' should be used. If interfaces is true (the default), you will need to manually supply any methods excluded from delegation that are required for the interface.- Since:
- 2.3.0
- Default:
- {}
-
-
-
includes
java.lang.String[] includes
List of method and/or property names to include when delegating. Only one of 'includes', 'includeTypes', 'excludes' or 'excludeTypes' should be used. For convenience, a String with comma separated names can be used in addition to an array (using Groovy's literal list notation) of String values. The default value is a special marker value indicating that no includes are defined; all fields are included if 'includes' remains undefined and 'excludes' is explicitly or implicitly an empty list. If interfaces is true (the default), you will need to manually supply any methods not included via delegation that are required for the interface.- Since:
- 2.2.0
- Default:
- {"<DummyUndefinedMarkerString-DoNotUse>"}
-
-
-
includeTypes
java.lang.Class[] includeTypes
List of interfaces containing method signatures to include when delegating. Only one of 'includes', 'includeTypes', 'excludes' or 'excludeTypes' should be used. The default value is a special marker value indicating that no includeTypes are defined. If interfaces is true (the default), you will need to manually supply any methods excluded from delegation that are required for the interface.- Since:
- 2.3.0
- Default:
- {groovy.transform.Undefined.CLASS.class}
-
-