Formal model for defender method resolution

David Holmes David.Holmes at oracle.com
Fri Jan 28 18:03:21 PST 2011


Alex,

 > Again, why do defenders if defending a method in a top superinterface
 > is going to be undone by "accidental" overriding (by rather hopeless
 > abstract methods) in subinterfaces?

Let's not forget that the primary use-case for defenders is to allow us 
to add _new_ methods to interfaces together with an implementation so 
that (most) existing classes will continue to compile and execute 
correctly. Adding defenders to existing methods is not the primary 
use-case and as per past discussions is somewhat perilous.

The crux of this matter is "accidental overriding" versus "deliberate 
overriding". If I override an interface method f() in B to specialize it 
compared to how it is defined in A then not only do I not want to 
inherit A's defender for f(), it would be inherently incorrect to do so 
because it does not implement the correct semantics.

You seem to want to cater for the programmer who accidentally overrides 
f() (to tweak javadoc in a semantically non-changing way) to still get a 
defender that exists somewhere in the inheritance hierarchy. Whereas I 
(and I think others) expect overriding (with no explicit defender) to 
mean reabstraction of the method.

Why are you against reabstraction? Reabstraction is always safe, if not 
always convenient. Silent inheritance may be convenient for some but is 
potentially unsafe.

Why should the addition of a defender in a super interface break my 
framework by allowing subclasses to silently inherit use of a defender 
that doesn't implement the semantics of the current type?

David Holmes

Alex Buckley said the following on 01/29/11 11:06:
> On 1/28/2011 3:55 PM, Neal Gafter wrote:
>> Die due to no f impl, exactly as it does today.  In this case it is 
>> irrelevant that one of the newly added methods has a default, as that 
>> default could not possibly be the one that the call resolves to.  This 
>> is a situation that occurs today and that is indeed what happens.
> 
> Why bother with defenders if a call to a defended method (and I think
> C.f _is_ defended by A.f, despite B.f) is going to die at runtime?
> 
> Not sure what you mean by "that default could not possibly be the one 
> that the call resolves to." The caller who causes execution of 
> invokeinterface B.f()B; has no idea whether the receiver class 
> implements f via a defender or via declaration/class inheritance.
> 
>>     If there's no error for B, and B.f _does_ inherit A.f's default, then
>>     invokeinterface B.f()B on a C may return an A that's not a B, and we
>>     definitely have unsoundness.
>>
>> Agreed!  Which is why B.f should not inherit A.f's default.
>>  
>>
>>     So either there should be an error on B;
>>
>>
>> Huh?  Why?  This is a simple case of reabstraction.  There's nothing 
>> wrong with B.  There might or might not be something wrong with some 
>> further derived type, but B is fine.
> 
> It's not reabstraction if A.f is given a defender after B gains f. 
> Defending the highest superinterface alone seems like a common migration 
> path, one we should support.
> 
>>     or no error yet _B.f inherits
>>     A.f's default and the inherited defender is typechecked in its new
>>     environment_.
>>
>> Huh?  Why?  When you reabstract a method, it has no implementation to 
>> inherit or check.
> 
> Again, why do defenders if defending a method in a top superinterface is 
> going to be undone by "accidental" overriding (by rather hopeless 
> abstract methods) in subinterfaces?
> 
> Alex
> 


More information about the lambda-dev mailing list