PROPOSAL: @OverrideAll annotation

rssh at gradsoft.com.ua rssh at gradsoft.com.ua
Tue Mar 31 07:02:55 PDT 2009


> 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