<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<font size="4"><font face="monospace">In a previous life, I was
involved in several static analysis efforts. One of the common
factors there is that annotations like
@ShouldntIgnoreReturnValue or @ShouldWashYourHands is that these
are always approximations, guidelines aimed at identifying
_likely bugs_ rather than _invalid programs_. Usually such
annotations beget requests for more annotations to refine the
behavior in increasingly rarefied corners.
@OverrideShouldInvoke seems like it would be equally subject to
this; it's a good starting point for "this is what the
superclass intends", but is unlikely to be precise enough to not
create new problems. <br>
<br>
The language, on the other hand, should mostly be in the
business of identifying _invalid programs_. If something is
important enough that the language should reject a program over
it, it should probably be part of the language, not an
annotation. (An obvious exception is @Override; in hindsight,
it was probably excessive exuberance to use the new shiny
annotation tool for this, rather than introducing a conditional
`override` keyword at the time (Java 5).) <br>
<br>
So my gut sense is that this belongs in an effort like Checkers
rather than in the language itself. <br>
</font></font><br>
<div class="moz-cite-prefix">On 2/9/2023 11:07 AM, Archie Cobbs
wrote:<br>
</div>
<blockquote type="cite" cite="mid:CANSoFxuRnN97Q83Z1kV3oCDi81V0eHUxfMTbqtUwh9ugzRbwew@mail.gmail.com">
<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" moz-do-not-send="true">@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" moz-do-not-send="true">@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" moz-do-not-send="true">@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" moz-do-not-send="true">@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>
</blockquote>
<br>
</body>
</html>