PROPOSAL: @OverrideAll annotation

Reinier Zwitserloot reinier at zwitserloot.com
Fri Apr 3 03:27:40 PDT 2009


What Derek said - this is not a good idea.

rssh: The proposal specifically states that each non-overridden method  
is to be generated with an empty body, or if that isn't possible due  
to a return type, the default return for that type (0/false/0.0/'\0'/ 
null).



  --Reinier Zwitserloot



On Apr 3, 2009, at 10:09, Derek Foster wrote:

> 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