Default method survey results

Yuval Shavit yshavit at akiban.com
Sat Aug 18 10:11:46 PDT 2012


On Aug 18, 2012, at 5:46 AM, "\"Zdeněk Troníček\"" <tronicek at fit.cvut.cz> wrote:

> Yuval Shavit napsal(a):
>> On Sat, Aug 18, 2012 at 3:35 AM, "Zdeněk Troníček"
>> <tronicek at fit.cvut.cz>wrote:
>>>
>>> 2) Iterator with remove() that throws UOE breaks the Liskov substitution
>>> principle. Mutable iterator is not a special case of immutable iterator.
>>
>>
>> Sorry for beating this horse, but I fail to see why this is the case.
>> Invoking remove() on an Iterator is obligated to do one of two things:
>> remove the last element that next() returned, or throw UOE. An iterator
>> with remove() that throws UOE conforms to this contract, and can be
>> replaced with any other iterator *about which nothing is known other than
>> it's an Iterator*.
>>
>> Taking wikipedia at face value, the LSP states:
>>
>>    Let be q(x) a property provable about objects x of type T. Then q(y)
>> should be provable for objects y of type S where is S a subtype of T.
>>
>> Let q(n) be "remove() throws UOE or removes the last element returned by
>> next()." I can prove q(x) for objects x of type Iterator, since that is
>> the
>> contract of Iterator.remove(). If some type S has a method remove() that
>> always throw UOE, then I can by definition prove the property "remove()
>> throws UOE" for objects y of S. In that case, I can also trivially prove
>> that "remove() always throws UOE or removes the last element returned by
>> next()" for objects y of S. So the LSP holds.
>
> 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).

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.


More information about the lambda-dev mailing list