PROPOSAL: @OverrideAll annotation

rssh at gradsoft.com.ua rssh at gradsoft.com.ua
Fri Apr 3 01:19:42 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.
>

May be this is not, what author of original proposal mean, but have
class annotation @OverrideAll, which does not generate any code, just
throw compile-time error when exists non-overridden member functions
is helpfull in some situations and prevent from hard to debug errors.



> 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