PROPOSAL: @OverrideAll annotation

Derek Foster vapor1 at teleport.com
Fri Apr 3 01:09:56 PDT 2009


My major problem with this proposal is that it doesn't seem to be straightforward to generate the bodies of methods that have to return something. Particularly for code such as implementations of the Visitor pattern.

Having un-overridden methods simply return null or zero is often not the right thing to do.

It's OK for generating methods that just take parameters, I suppose.

Still, having annotations generate code or otherwise affect the operation of a program is apparently a no-no per Sun's rules. If something like this is going to happen, I think it needs a new keyword or something rather than using an annotation.

(Although, personally, I don't think it would be such a bad thing if code generation via annotation existed, but were limited only to certain annotations in a specific package duly designated by the language implementors. Annotations have one nice quality that other ways of extending the language don't: You can create new "keywords" at will with no risk of breaking someone's perfectly-working code. If they don't import the annotation, they won't need to be impacted by it. I sort of wish there was an alternative to annotations (@@Foo instead of @Foo?) which was explicitly for the purpose of telling the compiler to generate boilerplate code of various types. Decorators in Python sort of serve this purpose, for instance.)

Derek

-----Original Message-----
>From: rssh at gradsoft.com.ua
>Sent: Mar 31, 2009 10:02 AM
>To: Gabriel Belingueres <belingueres at gmail.com>
>Cc: coin-dev <coin-dev at openjdk.java.net>
>Subject: Re: PROPOSAL: @OverrideAll annotation
>
>> Hi,
>>
>> I've written a new feature that might be comfortable to use for
>> someone. All input is welcomed.
>>
>
>It-is possible to do near same with annotation API (create a superclass
> which will override all)
>
>But -- sometime we really need to say, that all methods 'mus be'
>overriden.  (For example - when implementing Proxy pattern).
>In such case class-level annotation '@OverrideAll'  which tell compiler
>to check, that all methods must be overriden -- brilliant idea.
>
>
>
>
>
>> Regards,
>> Gabriel
>>
>> PROJECT COIN SMALL LANGUAGE CHANGE PROPOSAL FORM v1.0
>>
>> AUTHOR(S): Gabriel Belingueres
>>
>> OVERVIEW
>>
>> Add an @OverrideAll annotation to allow a class to override all
>> inherited methods with a trivial implementation. The resulting class
>> then could be used as the basis for a Null Object pattern (or even a
>> basic Mock object.)
>>
>>
>> FEATURE SUMMARY:
>>
>> The proposed @OverrideAll annotation will allow the class to override
>> all methods (from its superclasses and implemented interfaces) with a
>> trivial body, but the defined class can choose to implement specific
>> methods, replacing those that would be produced automatically by the
>> annotation.
>>
>>
>> MAJOR ADVANTAGE:
>>
>> Less coding for implementing Null Objects, or simple tests.
>>
>>
>> MAJOR BENEFIT:
>>
>> Let the compiler implement all uninteresting, non relevant behavior by
>> automatically providing with a trivial implementation of the inherited
>> methods.
>>
>>
>> MAJOR DISADVANTAGE:
>>
>> Might be a cause of NullPointerException if not used judiciously.
>>
>>
>> ALTERNATIVES:
>>
>> Implement all uninteresting methods by yourself by providing yourself
>> a trivial implementation (though actually popular IDEs can do this
>> automatically for you already.)
>>
>> EXAMPLES
>>
>> Given:
>>
>> class B {}
>>
>> public class A implements I1, I2 {
>>
>>   public static final int VAR = 1;
>>
>>   private B b;
>>
>>   public static Integer getSome() {
>>     return VAR;
>>   }
>>
>>   public A() {
>>   }
>>
>>   public A(B b) {
>>     this.b=b;
>>   }
>>
>>   public B getB() {
>>     return b;
>>   }
>>
>>   public void setB(B b) {
>>     this.b=b;
>>   }
>>
>>   protected void doProtected() { ... }
>>
>>   private void doPrivate() { ... }
>>
>>   A someNewA() { ... }
>>
>>   public synchronized void someSynchronized() {
>>   }
>>
>> }
>>
>> then:
>>
>> @OverrideAll
>> public class NullA extends A {
>> }
>>
>> is equivalent to declare:
>>
>> public class NullA extends A {
>>
>>   public NullA() {}
>>
>>   public NullA(B b) {
>>     super(b);
>>   }
>>
>>   public B getB() {
>>     return null;
>>   }
>>
>>   public void setB(B b) {
>>   }
>>
>>   protected void doProtected() {
>>    // empty
>>   }
>>
>>   A someNewA() {
>>    return null;
>>   }
>>
>>   public synchronized void someSynchronized() {
>>     // empty
>>   }
>>
>> }
>>
>> You may not want the default trivial implementation in some methods,
>> then you override them as usual:
>>
>> @OverrideAll
>> public class NullA extends A {
>>
>>   @Override
>>   public B getB() {
>>     return new B();
>>   }
>>
>>   @Override
>>   public synchronized void someSynchronized() {
>>     System.out.println("overridden");
>>   }
>>
>> }
>>
>> EXAMPLE 2
>>
>> Implement a trivial Collection interface just to test that adding
>> elements will increase the collection size:
>>
>> Currently:
>>
>> public class SomeCollection<E> implements Collection<E> {
>>
>>   private int counter;
>>
>>   @Override
>>   public boolean add(E arg0) {
>>     counter++;
>>     return true;
>>   }
>>
>>   @Override
>>   public boolean addAll(Collection<? extends E> c) {
>>     counter += c.size();
>>     return true;
>>   }
>>
>>   @Override
>>   public void clear() {
>>   }
>>
>>   @Override
>>   public boolean contains(Object arg0) {
>>     return false;
>>   }
>>
>>   @Override
>>   public boolean containsAll(Collection<?> arg0) {
>>     return false;
>>   }
>>
>>   @Override
>>   public boolean isEmpty() {
>>     return false;
>>   }
>>
>>   @Override
>>   public Iterator<E> iterator() {
>>     return null;
>>   }
>>
>>   @Override
>>   public boolean remove(Object arg0) {
>>     return false;
>>   }
>>
>>   @Override
>>   public boolean removeAll(Collection<?> arg0) {
>>     return false;
>>   }
>>
>>   @Override
>>   public boolean retainAll(Collection<?> arg0) {
>>     return false;
>>   }
>>
>>   @Override
>>   public int size() {
>>     return counter;
>>   }
>>
>>   @Override
>>   public Object[] toArray() {
>>     return null;
>>   }
>>
>>   @Override
>>   public <T> T[] toArray(T[] arg0) {
>>     return null;
>>   }
>>
>> }
>>
>> With the annotation:
>>
>> @OverrideAll
>> public class SomeCollection<E> implements Collection<E> {
>>
>>   private int counter;
>>
>>   @Override
>>   public boolean add(E arg0) {
>>     counter++;
>>     return true;
>>   }
>>
>>   @Override
>>   public boolean addAll(Collection<? extends E> c) {
>>     counter += c.size();
>>     return true;
>>   }
>>
>>
>>   @Override
>>   public int size() {
>>     return counter;
>>   }
>>
>> }
>>
>>
>> DETAILS
>>
>>
>> SPECIFICATION:
>>
>> A preliminary specification follows:
>>
>> As this feature is proposed as an annotation for code generation, no
>> changes to the current JLSv3 are needed.
>>
>> The annotation will generate "trivial" overridden implementations for
>> all methods not specified in the class, for each superclass in the
>> hierarchy (except Object) and implemented interface.
>>
>> - Static methods, private methods, final methods, constructors and
>> methods from class Object should never be generated.
>> - If some superclass (except Object) has already overridden some
>> Object class methods, then do NOT generate an empty overridden method
>> (to reuse current behavior.) (for example, if some superclass already
>> override toString(), equals() or hashCode().)
>>
>> - OPTIONAL: add a parameter to the @OverrideAll annotation to indicate
>> if @Deprecated methods should not be implemented.
>>
>> Trivial implementation for generated methods:
>>
>> - Methods returning void will have an empty body. (OPTIONAL: add a
>> parameter to the @OverrideAll annotation to indicate that it should
>> throw UnsupportedOperationException instead)
>> - Methods returning a primitive type will have a body returning the
>> same default value that would have for uninitialized instance
>> variables. (JLS section 4.12.5.)
>> - Methods returning a reference type will "return null;". (JLS section
>> 4.12.5.)
>> - The method will never return a covariant return type (because in
>> case of implementing a Null object, it should be undistinguished from
>> the common case)
>> - Methods that throws checked exceptions can be modified to delete the
>> throws clause. (ie. the trivial implementation should not throw
>> checked exceptions)
>> - Synchronized methods should retain that attribute.
>>
>>
>> COMPILATION:
>>
>> Compilation should proceed as usual, except that the annotation
>> processor would generate the code when it encounters an annotated
>> class.
>>
>> No changes to the class file format are needed.
>>
>>
>> TESTING
>>
>> Test cases should be done, including testing with classes implementing
>> several interfaces, classes with generics, inner classes, etc.
>>
>>
>> LIBRARY SUPPORT:
>>
>> No, except creating the new annotation.
>>
>>
>> REFLECTIVE APIS:
>>
>> No changes foreseen.
>>
>>
>> OTHER CHANGES:
>>
>> Output of javadoc tool.
>>
>>
>> MIGRATION:
>>
>> Just add the annotation to class level, and erase your trivially
>> implemented overridden methods.
>>
>>
>> COMPATIBILITY
>>
>> BREAKING CHANGES:
>> All existing programs remain valid.
>>
>> EXISTING PROGRAMS:
>> The semantics of existing class files and legal source files are
>> unchanged by this feature.
>>
>>
>> REFERENCES
>>
>> EXISTING BUGS:
>>
>> None that I know about.
>>
>> URL FOR PROTOTYPE:
>>
>> None at this time.
>>
>>
>
>
>




More information about the coin-dev mailing list