Virtual extension methods -- a strawman design

Pavel Minaev int19h at gmail.com
Mon May 17 01:42:37 PDT 2010


On Mon, May 17, 2010 at 12:47 AM, Gernot Neppert <mcnepp02 at googlemail.com>wrote:

> I find the notion of "default implementations of interface methods" a
> little strange.
> Isn't that an oxymoron?
>
> In my understanding, an interface declares the set of methods that a
> are needed to implement the functionality that the interface was
> designed to provide. If any one method can be implemented by means of
> calling other interface methods, then it is strictly speaking not
> necessary at all. *)
>
> So, if one comes up with a new method for an existing interface, I see
> two possibilities:
>
> 1. The method can be expressed by invoking other methods. Then, why
> not simply do that? I can see nothing bad about
> "Collections.sort(List<?)" or similar static helpers.
>
> 2. The method is "original" in its declared functionality. Thus, it
> can not be expressed by invoking existing methods. Thus, how can you
> provide a default implementation?
>

You miss a third case, which is a combination of the two above. Namely, the
method can be expressed by invoking other methods in the most general case
(that's our "default implementation"), but specific implementation of an
interface may have a more efficient way of implementing this method. On one
hand, you want simple implementations to be able to define the absolute
minimum of methods. On the other, you want more advanced implementations to
provide operations that are as efficient as possible, which, normally, means
specialized implementations of them.

Indeed, an existing example of an "interface" of this kind is abstract class
java.io.InputStream - its only abstract method is a single-byte read(), and
all other forms of read, such as e.g. read(byte[]), have default
implementations defined in terms of that. Of course, in practice, any
efficient implementation of InputStream would override read() and
read(byte[]) separately, so as to optimize the latter.

Note how InputStream has to be an abstract class today because of this, with
all the restrictions and limitations it entails; while it could - arguably,
more appropriately - be an interface with this proposal.

Another example of this is Collection#size(). Technically, it could be
defined on any Iterable, with the default implementation just iterating and
counting elements until it reaches the end - this is a reasonable
implementation for singly-linked lists or lazily generated sequences, for
example. However, most actual collections, such as ArrayList, would rather
override it to provide an efficient O(1) implementation. Indeed, this
proposal would enable the addition of size() to Iterable in an entirely
backwards-compatible way - all existing implementations of Collection would
end up implementing Iterable#size(), and all Iterables which aren't
Collections (and otherwise don't have size() defined on them) would gain the
default implementation for size(), which, while not efficient, is guaranteed
to behave correctly.

Similar reasoning is applicable to Collection#contains, Collection#isEmpty,
Collection#toArray, List#get, List#indexOf, List#lastIndexOf - and probably
more. Consequently, I'd expect all those to be lifted up to Iterable in
conjunction with this proposal, with default implementations provided there.


More information about the lambda-dev mailing list