groovy.transform.InheritConstructors Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package groovy.transform;
import org.codehaus.groovy.transform.GroovyASTTransformationClass;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Class annotation to make constructors from a super class available in a sub class.
* Do not use with {@link TupleConstructor}.
*
* {@code @InheritConstructors} saves you typing some boilerplate code.
*
* Example usage:
*
* class Person {
* String first, last
* Person(String first, String last) {
* this.first = first
* this.last = last.toUpperCase()
* }
* }
*
* {@code @groovy.transform.InheritConstructors}
* class PersonAge extends Person {
* int age
* }
*
* def js = new PersonAge('John', 'Smith')
* js.age = 25
*
* assert "$js.last, $js.first is $js.age years old" == 'SMITH, John is 25 years old'
*
* for this case, the PersonAge
class will be
* equivalent to the following code:
*
* class PersonAge extends Person {
* PersonAge(String first, String last) {
* super(first, last)
* }
* int age
* }
*
* You may add additional constructors in addition to inherited ones.
* If the argument types of a supplied constructor exactly match those
* of a parent constructor, then that constructor won't be inherited.
*
* Style note: Don't go overboard using this annotation.
* Typical Groovy style is to use named-arg constructors when possible.
* This is easy to do for Groovy objects or any objects following JavaBean
* conventions. In other cases, inheriting the constructors may be useful.
* However, sub-classes often introduce new properties and these are often best
* set in a constructor; especially if that matches the style adopted
* in parent classes. So, even for the example above, it may have been
* better style to define an explicit constructor for PersonAge
* that also set the age
property. Sometimes, consistent
* style is much more important than saving a few keystrokes.
*
* As another example, this:
*
* {@code @InheritConstructors} class CustomException extends RuntimeException { }
*
* is equivalent to this:
*
* class CustomException extends RuntimeException {
* CustomException() {
* super()
* }
* CustomException(String message) {
* super(message)
* }
* CustomException(String message, Throwable cause) {
* super(message, cause)
* }
* CustomException(Throwable cause) {
* super(cause)
* }
* }
*
*
* Advanced note:If you create Groovy constructors with optional
* arguments this leads to multiple constructors created in the byte code.
* The expansion to multiple constructors occurs in a later phase to
* this AST transformation. This means that you can't override (i.e. not
* inherit) the constructors with signatures that Groovy adds later.
* If you get it wrong you will get a compile-time error about the duplication.
* More examples:
*
* //--------------------------------------------------------------------------
* import groovy.transform.InheritConstructors
*
* @InheritConstructors
* class MyException extends Exception {
* }
*
* def e = new MyException()
* def e1 = new MyException('message') // Other constructors are available.
* assert 'message' == e1.message
*
*
* //--------------------------------------------------------------------------
* import groovy.transform.InheritConstructors
* class Person {
* String name
*
* Person(String name) {
* this.name = name
* }
* }
*
* @InheritConstructors
* class Child extends Person {}
*
* def child = new Child('Liam')
* assert 'Liam' == child.name
*
*
* @author Paul King
* @since 1.7.3
*/
@java.lang.annotation.Documented
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.TYPE})
@GroovyASTTransformationClass("org.codehaus.groovy.transform.InheritConstructorsASTTransformation")
public @interface InheritConstructors {
/**
* Whether to carry over annotations on the copied constructors.
* Currently Closure annotation members are not supported.
*
* @return true if copied constructor should keep constructor annotations
*/
boolean constructorAnnotations() default false;
/**
* Whether to carry over parameter annotations on the copied constructors.
* Currently Closure annotation members are not supported.
*
* @return true if copied constructor should keep parameter annotations
*/
boolean parameterAnnotations() default false;
}