PRE-PROPOSAL: Extension methods
Neal Gafter
neal at gafter.com
Wed Mar 18 10:23:46 PDT 2009
On Tue, Mar 17, 2009 at 11:56 PM, Kevin Krouse <kevin.krouse at gmail.com> wrote:
> I'm interested in extension methods.
I'll write up a full proposal if I have any indication it's something
Joe/Sun(/IBM) would consider for project Coin. The basic idea would
work like this:
Within a static method, you can use "this" as an new qualifier on the
first method parameter, which must be a reference type. This would be
reflected in the class file format as either a new flag, or a new
classfile attribute ("ExtensionMethod") on the method.
When an extension method has been statically imported, you can use it
as if it is a member of the type of its first argument. The name
lookup rules for a method invocation
o.f(...)
are augmented as follows. When identifying candidates for overload
resolution, if no accessible candidates of the correct name are found
as a member of the static type of the receiver (JLS 15.12.1 and
15.12.2), then we consider as candidates those statically imported
methods with name f, and perform the overload resolution among them as
if the invocation had been written
f(o, ...)
This is backward compatible, as it assigns meanings to expressions
that were previously errors, and does not change the meaning of code
that was not previously an error.
There are a number of benefits to this approach. A large number of
static utility class members can and probably should be retrofitted to
use extension methods, making it possible to use a much more
convenient syntax for common operations.
import static java.util.Collections.sort;
List<Integer> list = ...
list.sort(); // uses Collections.sort extension method
Similarly, it allows extension methods to operate on arrays
import static java.util.Arrays.sort;
String[] strings = ...
strings.sort(); // uses Arrays.sort extension method
The syntactic convenience of this is greater (i.e. code becomes more
readable) when multiple invocations work together in an expression.
One of the more important benefits of this approach is that it enables
future language changes to be defined by syntactic translation, while
allowing more flexible retrofitting of those language changes onto
existing APIs than would be possible without extension methods. For
example, one could define an ARM construct by translation of something
like
protected (expression) statement
into
{
Type1 $t1 = expression
Type2 $t2 = $t1.protectedStart();
try {
statement
} finally {
$t2.protectedEnd();
}
}
(with appropriate inversion of suppressed exceptions, if you please).
Then, to add support for this new ARM construct to some particular API
you would either add these methods to the API or define extension
methods. If done using extension methods or final instance methods,
they are likely to be inlined by HotSpot if used in frequently
executed code, so the performance overhead is vanishingly small.
Since extension methods can be added even to existing interfaces
without breaking compatibility, such an ARM construct could be
retrofitted onto many more APIs than the currently proposed construct.
It could easily be retrofitted onto java.util.concurrent.locks.Lock,
for example.
See also http://www.javac.info/ExtensionMethods.html
More information about the coin-dev
mailing list