My ¢2 on Java Extension Methods
A while a go Neil Gafter proposed extension methods as a new feature in Java 7. This is an interesting proposal and if it is implemented, it would make Quaere even better. I'll skip the tired list sorting example from the discussions and think out loud about how Quaere would benefit from extension methods.
First lets look at some simple features. Today, you can union two sequences using the union static import:
List<Integer> numbersA = Arrays.asList(0, 2, 4, 5, 6, 8, 9);
List<Integer> numbersB = Arrays.asList(1, 3, 5, 7, 8);
Iterable<Integer> uniqueNumbers = union(numbersA, numbersB);
If we can introduce the union method as an extension method on the List interface, the example could be written like this:
List<Integer> numbersA = Arrays.asList(0, 2, 4, 5, 6, 8, 9);
List<Integer> numbersB = Arrays.asList(1, 3, 5, 7, 8);
Iterable<Integer> uniqueNumbers = numbersA.union(numbersB);
It's not a huge thing, but it makes the queries a little nicer because it now read entirely from left to right. We could also use extensions to make queries a little more compact. Instead of writing:
List<Integer> numbers =
Arrays.asList(5, 4, 1, 3, 9, 8, 6, 7, 2, 0);
Iterable<Integer> lowNums =
from("n").in(numbers).
where(lt("n", 5)).
select("n");
...we could do something like this...
List<Integer> numbers =
Arrays.asList(5, 4, 1, 3, 9, 8, 6, 7, 2, 0);
Iterable<Integer> lowNums =
numbers.where(lt("n", 5));
However, I think we'd have to keep the more verbose query syntax as it is today, because it is a little cumbersome to write advanced queries without any language support.
The biggest potential lies in how predicates are expressed. Today, we have to write the n < 5 predicate as lt("n",5). Both Thomas Mueller and Faraz Amhed are working on some interesting alternatives that would enable us to write predicates like this in a more straight forward manner, but none of these have made it into Quaere yet. With extension methods we could improve today's implementation by extending java.lang.String. If we did, the predicate could look like this n.lt(5). Extending a common class like String has its issues and .NET developers have experienced this with C# extension methods.
While we're at C#, I'd like to contribute my own suggestion on how extension methods could be implemented in Java. I really like the C# take on this. Below is an example of how we could extend .NET's IList interface with the union method from earlier. This is of course for example only as LINQ already does this.
public static IEnumerable<T> union(this IList<T> sourceA, IList<T> sourceB) {
List<T> result = new List<T>();
result.add(sourceA);
foreach (T b in sourceB) {
if (!result.Contains(b)) {
result.Add(b);
}
}
}
Notice the this keyword on the first argument, this indicates that the C# compiler should treat this method as an extension. Read my Bare Naked LINQ post for more on .NET extension methods.
I'd like to see a similar approach if extensions are added to Java. This preserves a familiar syntax and uses familiar concepts to achieve it. After all, extension methods only need to be compile time magic - there is no need to change the JVM.
Technorati tags:
Java,
.NET,
Quaere