Re-specification and re-abstraction

Brian Goetz brian.goetz at oracle.com
Thu Dec 22 06:14:40 PST 2011


The tension here is between respecting the existing language behavior, 
intended or not -- where exact redeclarations of interface methods is a 
no-op -- and how we want this "new" feature to work, and who loses when 
existing usage patterns conflict with the desired usage patterns for the 
new feature.

The existing semantics were designed to respect the no-op-ness of these 
redeclarations, effectively making them "invisible" to the default 
calculation, rather than give a potentially surprising new meaning to a 
hitherto meaningless (but used in practice) construct.

Neither answer is obviously right, or even good (and anyone claiming 
otherwise has not thought through it enough.)  Its only a matter of 
which alternative is less bad, and there's arguments on both sides.  We 
went back and forth on this one a few times already, and may well go 
back and forth on it a few times more before we're done.


On 12/22/2011 2:25 AM, Peter Levart wrote:
> On 12/22/11, David Holmes wrote:
>> One of the things that concerns me in the current State of the Lambda is
>> the fact that re-specification of method on a sub-interface does not
>> re-abstract the method, but continues to allow any default from a super
>> interface to be applied to that method. This is inherently wrong in my
>> opinion.
>>
>> Consider this fictitious but plausible example.
>>
>> We have the present Map interface. We also have a ConcurrentMap
>> interface that adds some additional methods that provide atomicity for
>> compound actions on maps that support concurrent access.
>>
>> Suppose that ConcurrentMap actually re-specified each of the Map methods
>> to add various thread-safety and atomicity guarantees.
>>
>> Now suppose that the maintainer of Map decides to take advantage of
>> default methods and adds default implementations to some of those Map
>> methods. This is not done with ConcurrentMap in mind and those
>> implementations offer no specific thread-safety or atomicity guarantees.
>> It should be obvious that those implementations are not likely to be
>> valid for any class that implements ConcurrentMap.
>>
>> Given the current semantics however, if I were to write a class that
>> implements ConcurrentMap and accidentally forgot to implement those
>> methods for which a default exists in Map, then my class will in fact
>> "inherit" those implementations. And in doing so my class would be
>> completely broken, but I would be unaware of it.
>>
>> To me this is completely wrong - we should never sacrifice correctness.
>> A supertype does not in general know about any subtypes and so a
>> supertype's default implementation should not apply if the subtype has
>> redefined that method. Any change to the "documentation" of a method is
>> a change to its specification. Only the author of that change is in a
>> position to say whether a default implementation in a supertype is still
>> applicable - so to assume that it is by default (no pun intended) is
>> just wrong in my view.
>>
>> If redefinition of a method always re-abstracted it then, I think, no
>> explicit syntax for re-abstraction would be needed.
>>
>> David Holmes
>>
>
> I aggree. Only the author of the interface should say when an if the "new" default on a superinterface is adequate. I don't see any drawback when re-specification of a method in a subinterface has the semantics of re-abstraction compared to current state where the default is inherited. It certainly doesn't break any code.
>
> Looking from the perspective of code evolution: if an interface method was abstract (non-default) at the start than any non-abstract implementations of this interface or subinterface already specifies a concrete implementation for that method. Changing this abstract method to a default method on a superinterface does not break anything even if this method is re-abstracted on any subinterface (because class allways wins).
>
>   Regards, Peter
>
>>
>


More information about the lambda-dev mailing list