<div dir="ltr"><div>Just throwing this out there - I'm curious whether this idea resonates with anyone else... or alternately offends...</div><div><br></div><div>First, a big picture observation:</div><div><br></div><div>There is a lot of "activity" in Java centered around the superclass-subclass relationship. For example, we have the <span style="font-family:monospace">protected</span> keyword.  We have the <span style="font-family:monospace">final</span> keyword. We have a bunch of rules around how constructors are allowed (or not allowed) to invoke <span style="font-family:monospace">super()</span>. We have <span style="font-family:monospace">@Overrides</span>. We have <span style="font-family:monospace">abstract</span> methods that force behavior on subclasses.<br></div><div><br></div><div>Basically, all of this stuff amounts to a somewhat ad hoc "API" that a superclass defines and a subclass uses (and in some cases, vice-versa).<br></div><div><br></div><div>But this "API" is not always clearly or fully defined. For example, bugs caused by 'this' escapes result from what can be described as an ambiguity in the "API" between superclass and subclass.<br></div><div><br></div><div>I guess I'm just saying that this "API" and how we define it (or fail to define it) is an area of interest to me.<br></div><div><br></div><div>OK, back to earth...</div><div><br></div><div>Here's a proposal that addresses one more little bit of this "API". I'm on the fence as to whether this would be worthwhile and am curious what others think.<br></div><div><br></div><div>The problem is this: often a superclass method <span style="font-family:monospace">foo()</span> implements some important superclass functionality, but it is not final so that it can be overridden. In these cases, the superclass often wants to be able to specify "If you override this method, then you should also invoke <span style="font-family:monospace">super.foo()</span> at some point unless you really know what you're doing". An example of such a method is <span style="font-family:monospace">Object.finalize()</span>.</div><div><br></div><div>There are arguments that such methods are bad style - instead, there should be a separate empty method provided for subclasses to override. So this idea would have to be weighed against that. But regardless, today there are lots of examples of such methods out there already.<br></div><div><br></div><div>The rough proposal is:</div><div><ul><li>Add a new annotation <span style="font-family:monospace">@OverrideShouldInvoke</span>. If a method <span style="font-family:monospace">Sub.foo()</span> overrides a superclass method <span style="font-family:monospace">Sup.foo()</span> that has an <span style="font-family:monospace">@OverrideShouldInvoke</span> annotation, and nowhere in <span style="font-family:monospace">Sub.foo()</span> does it invoke <span style="font-family:monospace">Sup.foo()</span> (via a <span style="font-family:monospace">super.foo()</span> expression), then an error occurs.<br></li><li>Add a new property <span style="font-family:monospace">boolean withoutInvokingSuper default false</span> to the <span style="font-family:monospace">@Overrides</span> annotation that allows <span style="font-family:monospace">Sub.foo()</span> to suppress this error if it "really knows what it's doing".<br></li></ul></div><div>For simplicity, we'd only count invocations of the overridden method exactly, not some overloaded variant. So for example if an override of <span style="font-family:monospace">ArrayList.add(E)</span> invoked <span style="font-family:monospace">super.add(int, E)</span>, that wouldn't count. Or, if you wanted to get fancy, you could make this optional via something like <span style="font-family:monospace"><a class="gmail_plusreply" id="plusReplyChip-4">@Override</a>ShouldInvoke(allowOverloads = true)</span>.<br></div><div><br></div><div>Here's are some examples of where you might want to use this:</div><div><br></div><div style="margin-left:40px"><span style="font-family:monospace">public class Object {</span></div><div style="margin-left:40px"><span style="font-family:monospace"><br></span></div><div style="margin-left:40px"><span style="font-family:monospace">    <a class="gmail_plusreply" id="plusReplyChip-3">@OverrideShouldInvoke</a></span></div><div style="margin-left:40px"><span style="font-family:monospace">    protected native Object clone() throws CloneNotSupportedException;</span></div><div style="margin-left:40px"><span style="font-family:monospace"><br></span></div><div style="margin-left:40px"><span style="font-family:monospace">    @OverrideShouldInvoke<br>    protected void finalize() throws Throwable {<br>        ...<br>    }</span></div><div style="margin-left:40px"><span style="font-family:monospace">}</span></div><div style="margin-left:40px"><span style="font-family:monospace"><br></span></div><div style="margin-left:40px"><span style="font-family:monospace">public class FileOutputStream extends OutputStream {</span></div><div style="margin-left:40px"><span style="font-family:monospace"><br></span></div><div style="margin-left:40px"><span style="font-family:monospace">    <span style="font-family:monospace"><span style="font-family:monospace"><a class="gmail_plusreply" id="gmail-plusReplyChip-3">@OverrideShouldInvoke</a></span></span></span></div><div style="margin-left:40px"><span style="font-family:monospace">    public void close() throws IOException {</span></div><div style="margin-left:40px"><span style="font-family:monospace">        ...</span></div><div style="margin-left:40px"><span style="font-family:monospace">    }<br></span></div><div style="margin-left:40px"><span style="font-family:monospace">}</span></div><div style="margin-left:40px"><span style="font-family:monospace"><br></span></div><div style="margin-left:40px"><span style="font-family:monospace">public abstract class AbstractExecutorService implements ExecutorService {</span></div><div style="margin-left:40px"><span style="font-family:monospace"><br></span></div><div style="margin-left:40px"><span style="font-family:monospace">    <span style="font-family:monospace"><a class="gmail_plusreply" id="gmail-plusReplyChip-3">@OverrideShouldInvoke</a></span></span></div><div style="margin-left:40px"><span style="font-family:monospace">    public Future<?> submit(Runnable task) {</span></div><div style="margin-left:40px"><span style="font-family:monospace">        ...</span></div><div style="margin-left:40px"><span style="font-family:monospace">    }<br></span></div><div style="margin-left:40px"><span style="font-family:monospace">}<br></span></div><div><br></div><div>Thoughts?<br></div><div><br></div><div>-Archie</div><div><br></div><div>--<br></div><div><div dir="ltr" data-smartmail="gmail_signature">Archie L. Cobbs<br></div></div></div>