Re-specification and re-abstraction
Greg Dennis
gdennis at alum.mit.edu
Fri Dec 23 14:44:30 PST 2011
Sorry, I should have been a little more careful with my example. Of
course C and D should be interfaces and C should be declared to extend
D. But while I'm at it, maybe this is a slightly less contrived
example:
interface Sorter {
/**
* Sorts the elements in the given list.
*/
void sort(List lst);
}
interface StableSorter extends Sorter {
/**
* Sorts the elements in the given list, maintaining the
* relative order of equal elements.
*/
void sort(List lst);
}
If a default implementation of Sorter were later provided that does
not do a stable sort, it would break the StableSorter contract.
Greg
On Thu, Dec 22, 2011 at 8:56 PM, Greg Dennis <gdennis at alum.mit.edu> wrote:
>>>> 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 no-op-ness of "exact redeclaration of interface method" is respected
>>> either way if the definition of "exact" is adequate.
>>
>> Yes, if you exactly redeclare the default too, it is also a no-op. So,
>> more precise statement: "exact redeclaration of the return type, name,
>> and signature, but no default clause."
>
> Long-time lurker here chiming in. It seems to me a problem with this
> calling this an "exact redeclaration" is that all of these things may
> stay the same (return type, name, signature), and yet the *contract*
> of the method may still have changed. That new contract may be given
> in the Javadoc accompanying the method, but does not require any
> change in method signature.
>
> For example, consider class C:
>
> class C {
> /**
> * Precondition: a is not null
> */
> R method m(A a);
> }
>
> When a precondition is false, the method can do anything --- return a
> value, throw an exception, go into an infinite loop, anything. Now
> class D may extend it and drop the precondition:
>
> class D {
> /**
> * If a is null, returns null.
> */
> R method(A a);
> }
>
> Since the precondition is dropped, D is still a true subtype of C. But
> if the author of C were to later provide a default implementation to m
> that throws an exception when given a null argument, it would break
> the contract of D. That seems very undesirable.
>
> The argument is that the current semantics preserves the "no-op"
> behavior of a redeclaration. Another way to look at it is that a
> redeclaration has always meant "reabstract" and that the "no-op"
> treatment has merely been an optimization since concrete
> implementations in interfaces were never before possible :)
>
> I'll now scurry back into lurker mode ...
>
> Greg
More information about the lambda-dev
mailing list