Extension methods proposals

There’s a quite interesting discussion in the blogosphere about proposed extension methods feature for Java 7. The problem tackled by this proposal is how to extend an API (interface) with new methods without breaking existing implementations. The example used in a discussion is a List interface and the sort() method. In order to add another method to the existing interface, Java developers today create static utility functions. Take for example the java.util.Collections class, which is a set of static helper methods for working with collections. Among them is of course the aforementioned sort method. Here’s a simple example:

public class Extension {
    public static void main(String[] args) {
        ArrayList list = new ArrayList() ;
        list.add("123");
        list.add("678");
        list.add("456");
        java.util.Collections.sort(list);
        System.out.println(list);
    }
}

Here we have defined a list and used static sort method of the java.util.Collections class to sort it. As a result we get the following output

[123, 456, 678]

Since Java 5, we are able to do static imports so we can do this in a bit more elegant way. The previous example can be rewritten as follows

import static java.util.Collections.sort;

public class Extension {
    public static void main(String[] args) {
        ArrayList list = new ArrayList() ;
        list.add("123");
        list.add("678");
        list.add("456");
        sort(list);
        System.out.println (list);
    }
}

There are many things about static import feature that are declared as “controversial” by developers, such as shadowing of imports by locally defined static methods and importing more then one static method with the same name (look at this post by David Flanagan for more info).

The idea of “extension methods” for Java 7 is based on static imports and it adds another “feature” for such methods. It all started with the
initial Neal Gafter’s proposal. The proposal is to enable usage of statically imported functions as methods of the original interface. So instead of

sort(list)

we can use it in a more natural way

list.sort()

Some of the potential problems of this use-site extension methods approach as called and spotted by Peter Ahe are the same as with ordinary statically imported methods. Additionally, it transparently enables end users to extend final classes which could be one more source of bugs in the applications.

That’s why he proposes the declaration-site extension methods mechanism which means that API developer must specifically mark methods that could be extended in this way. For example

void sort() import static java.util.Collections.sort;

Stephen Colebourne joined the discussion arguing that Peter’s approach prevents users to extend the API which is probably the most important usage of this mechanism.

He proposed usage of the special syntax for using extension methods, such as

list.do.sort();

or

list->sort();

and that is probably better to annotate methods we want to be extensible (if we must) since it will give more flexibility over Peter’s approach, such as

@ExtensionMethod
public void sort(List list) { ...}

But this mechanism changes the language syntax, which is probably something Neal wanted to avoid in the first place.

Finally, there are mechanisms that other languages use for this kind of tasks (but of course require language syntax change). For example, in Groovy you can use Categories to do this. Take a look at this example.

class EnhancedInteger {
    static boolean greaterThanAll(Integer self, Object[] others) {
        greaterThanAll(self, others)
    }
    static boolean greaterThanAll(Integer self, others) {
        others.every{ self > it }
    }
}


use(EnhancedInteger) {
    assert 4.greaterThanAll(1, 2, 3)
    assert !5.greaterThanAll(2, 4, 6)
    assert 5.greaterThanAll(-4..4)
    assert 5.greaterThanAll([])
    assert !5.greaterThanAll([4, 5])
}

In any case I think this is an important topic (which is something you can see by the number of comments found on aforementioned blog posts) and it is important to find a balance between the feature and how it will affect the syntax. I think it will all end up with Neal’s original proposal with note to developers “use with care”. But one thing is certain, it is great to see this kind of topics discussed in blogosphere this early in the process. What’s your take on this?