Once an API has been published, you can't add methods to it without breaking backward compatibility. That's because implementations of the old version of the interface don't provide an implementation of any new methods. You can use abstract classes instead of interfaces, and only add concrete methods in the future. Unfortunately, that limits you to single inheritance.
One way API designers work around this limitation is to add new
functionality to an interface by writing static utility functions. For
example, java.util.Collections.sort
acts as an extension
of java.util.List
. But such methods are less convenient
to use, and code written using them is more difficult to read.
Extension methods enable programmers to provide additional methods that clients of an interface can elect use as if they are members of the interface. Todd Millstein's Expanders are the most full-featured version of this feature. The simplest version of this feature that I advocate would be to enable statically-imported methods to be used as if members of their first argument type. For example:
import static java.util.Collections.sort;
...
List<String> list = ...;
list.sort();
One of the biggest advantages of extension methods is that they enable more flexible extension of the language moving forward. For example, suppose a new Automated Resource Management statement were defined in terms of invoking an acquire() method, and then later invoking a release() method on the result of the earlier acquire(). Clearly existing APIs such as Closeable do not implement this protocol, but by providing static factory methods they could be made to act as if they do. Such a statement could then be easily retrofitted onto other resource APIs, such as java.util.concurrent.locks.Lock (an interface), simply by providing extension methods. This retrofitting introduces no breaking changes, since the underlying APIs are not changed.