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