Declaration-Site Extension Methods

Neal Gafter and others are suggesting to add extension methods to the Java programming language. To be clear about Neal’s proposal, I will call it use-site extension methods. I call them so because the user specifies which extension methods are to be used.

To be concrete, let me repeat Neal’s example of adding a sort() method to java.util.List:

import static java.util.Collections.sort;

List<String> list = …;
list.sort();

A clear benefit to this is that it builds on an existing language construct, static import. And as such, it may seem to be a simple extension. Unfortunately, in Java, nothing is simple. By itself, static import has a number of limitations. For example, you cannot import a method with the same name from different types. [update: actually you can, see also the comments.]

Another potential issue is source compatibility: currently, adding a public method to a final class is a source compatible change. However, if you add use-site extension methods, this is no longer true. A client of the final class could be extending it with a method with the same name as the new method. Imagine that the signature of the added method is compatible with the extension method, in this case, the compiler will not flag this as a potential error, instead it will silent change what method is called. This is a potential for subtle bugs.

An alternative is declaration-site extension methods in which the library designer specifies extension methods when declaring the type to be extended.

For example, instead of having each user of java.util.List import a sort method, the interface could declare that it is extended by java.util.Collections.sort:

package java.util;
interface List<E> … {
  …
  void sort() import static java.util.Collections.sort;
  …
}

This will instruct the compiler to compile:

java.util.List<String> list = …;
list.sort();
as if the user had written:
java.util.List<String> list = …;
java.util.Collections.sort(list);

Declaring sort within java.util.List<String> should only affect the compilation of clients of the interface. The compiler must record that the interface is extended by adding a new kind of attribute to the class file, but this should be defined to affect neither the calculation of default serialVersionUID nor how methods are looked up by the JVM.

Acknowledgements

Alex Buckley coined the terms use-site extension methods and declaration-site extension methods inspired by Thorup and Torgersen’s use-site variance. See also, Adding Wildcards to the Java Programming Language.

54 Responses to “Declaration-Site Extension Methods”

  1. We’ve gone through a couple of years of “let’s not mess with anything in the language except for super-simple things like strings in switch and binary literals”. Then it was “ok, maybe we really need closures so that we can write ParallelArray without a hundred helper methods”. And I agree with that–the value gained for the added complexity seems worth it.

    But I don’t see the value gain for extension methods, be they use-site or declaration-site. I must be missing something.

    There isn’t anything so awful about Collections.sort(list); that we would need a whole new library mechanism, right? In Java 7, one could add forEach, map, etc. to Collections, and we’d just write Collections.map(list, #(f:SomeType) => expr). Or use a static import.

    Is there some usecase that goes beyond this?

  2. Peter Ahé says:

    Cay,

    I don’t see the value of extension methods. When I heard that use-site extension methods were proposed in a JSR, I felt I had to propose an alternative solution that wouldn’t have the same downsides as the original proposal.

    Smalltalk has extension methods and it doesn’t make the APIs easier to understand or use.

    Cheers,
    Peter

  3. Daniel says:

    I’d much rather have declaration-site extension methods than nothing at all.

    Java needs to evolve at a faster pace if it wants to remain competitive.

    I’m personally only still using Java because I have the inertia of a half million lines of code to deal with. I’d love to switch to Scala.

    It’s sad how fast C# is evolving compared to Java.

    The “let’s not mess with the language or JVM” ideology is doing serious damage to the Java platform.

  4. David Conrad says:

    I think it’s strange that this (otherwise highly informative) discussion went right down to the end before anyone even mentioned C# and its extension methods, which is where I know the term from.

    It sounds to me like the conclusion was that extension methods aren’t worth it because the use case for them is too narrow to be worth the trouble. So, was it a mistake to add them to C#? Or are there more ambitious use cases in C# that made extension methods worth the cost? LINQ? No one seems to be asking those questions, and that worries me.

    Let me clarify something. I don’t think Java should add features just because C#, or any other language, has them. There shouldn’t be any “feature envy”, and every addition to Java has to be justified on its own merits, fit the Java style, pay its own freight, etc. etc.

    But we need to be aware of the activity going on over there. Is the lack of a compelling use case for extension methods in Java due to Java’s vision not being ambitious enough?

Leave a Reply