Default method survey results

"Zdeněk Troníček" tronicek at fit.cvut.cz
Sat Aug 18 12:34:48 PDT 2012


Yuval Shavit napsal(a):
> On Aug 18, 2012, at 5:46 AM, "\"Zdeněk Troníček\"" <tronicek at fit.cvut.cz>
> wrote:
>> Although this reasoning is right, it is not about immutable iterator.
>> q(x)
>> for immutable iterator is "remove() throws UOE" which apparently does
>> not
>> hold true for mutable iterator.
>> The property you state ("remove() throws UOE or removes the last
>> element...") holds true for general iterator.
>> And when you add "remove() { throw new UOE(); }" to Iterator, it becomes
>> immutable iterator, regardless of whether the name remains Iterator or
>> changes to ImmutableIterator.
>
> I think I understand your point now. If the javadoc says "may throw
> UOE or remove the last element next() returned," and a default method
> provides one of those implementations, does the default method's
> implicit contract override the javadoc's explicit one? I say no
> (assuming the two are compatible, which they are in this case).

Javadoc may strengthen preconditions and loosen postconditions. So,
strictly speaking, we can declare remove() that throws UOE and define the
contract as "may throw UOE or remove the last element". It has the same
logic as if you declare the class GrObject, its subclasses Ellipse and
Rectangle, and then implemented the draw method in GrObject so that it
draws rectangle and argue that it follows the contract (that could be "it
draws a shape").
Although technically this follows the substitution principle, I do not
think this is a good design.

> Maybe this is an argument in favor of the "default" keyword: it makes
> it clear that this is just a default implementation, not necessarily
> the only or even the best. That said, this happens in abstract
> classes, too. The fact that AbstractList throws UOE on set(i, E)
> doesn't mean it and its subclasses are contractually obligated to be
> unmodifiable.

Concerning the AbstractList, javadoc of its method add(), for example,
says "This implementation always throws an UnsupportedOperationException."
Without any doubts this is strengthening of the method postcondition and
so any subclass that overrides add() with an implementation that does not
throw UOE, violates the Liskov substitution principle.
As any other principle, the substitution principle is not dogma and its
violation is not disaster if properly justified.
But for the case of remove() in Iterator, justification is poor.


More information about the lambda-dev mailing list