Formal model for defender method resolution
David M. Lloyd
david.lloyd at redhat.com
Mon Jan 31 18:31:34 PST 2011
Honestly I don't think of this as re-abstraction. It's the *default*
implementation, not *the* implementation. You're saying, "if nobody
else in the hierarchy says otherwise, do this". Especially if the
syntax is different.
Anyway, if someone has re-overridden a defender method it probably means
they did so *before* the defender method existed, and they probably
already have an implementation for it so it doesn't matter. If they
override a defender method after the fact, they'd probably change the
default if they wanted to.
That said it would be nice if one could *explicitly* remove the default
implementation by overriding it. Maybe "default abstract" or something.
On 01/31/2011 08:19 PM, Brian Goetz wrote:
> All things being equal, I would agree with (1) and (3). Unfortunately
> reabstraction of defended methods seems to complicate resolution, and
> given that people use reabstraction fairly infrequently now, it may be a
> better choice to accept some additional apparent inconsistency in
> exchange for simpler semantics.
>
> I am not sure I agree with (2), because it is not uncommon to see an
> overriding purely to add a note to the Javadoc, enough so that
> supporting reabstraction "breaks" the common intuition that
> (non-covariantly) overriding a method in an interface is a no-op.
>
>
>
> On 1/31/2011 8:56 PM, Howard Lovatt wrote:
>> Hi,
>>
>> I think it is best that a defended method can be re-abstracted (like
>> abstract classes currently do) for three reasons:
>>
>> 1. It is the expected behaviour. If you see "m();" in an interface,
>> you expect it to be abstract and you expect to have to implement it.
>> You should not be required to check the hierarchy to see if it is
>> inheriting something unexpected. If you forget to implement the method
>> you won't be warned, silently and potentially insidiously a default
>> will appear.
>>
>> 2. It is the only safe assumption. If someone is overriding a defended
>> method then they are doing so for some good reason. Commonly, the
>> semantics of the method are subtly altered and a modification to the
>> Javadoc is required to note the change. The fact that the semantics
>> have changed means that inheriting the method isn't safe and therefore
>> it should be re-abstracted.
>>
>> 3. It is important to be consistant with abstract classes, since
>> defender methods are similar to abstract classes and it will be
>> confusing if they behave differently. People may well start to use
>> defender methods were they previously used abstract classes, therefore
>> the two should be as interchangeable as possible.
>>
>> Cheers,
>>
>> -- Howard.
>>
>> On 29 January 2011 13:03, David Holmes<David.Holmes at oracle.com> wrote:
>>> 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
>>>>
>>>
>>>
>>
>>
>>
>
--
- DML
More information about the lambda-dev
mailing list