Wednesday, March 25, 2009

Extensions Methods In Java!

Note: Oracle has locked down java so this is no longer possible :-(


W00T!

I just added extension methods to java. It's a bit of a hack, but a small bit. (you need to replace the java.lang.Object class)

First, the hack, download and follow the instructions in the readme file of Java_Extensions.zip

Now you can run this test successfully...

package com.spun.util.extensions.tests;
import junit.framework.TestCase;

public class ExtensionsTest extends TestCase
{
public static class MyStringUtils extends ExtendableBase<String>
{
public String removeVowels()
{
StringBuffer b = new StringBuffer();
for (Character c : caller.toCharArray())
{
switch (c)
{
case 'a' :
case 'e' :
case 'i' :
case 'o' :

case 'u' :
break;
default :
b.append(c); } } return b.toString();
}
}
public void testname() throws Exception
{
String name = "Hello World".use(MyStringUtils.class).removeVowels();
assertEquals("Hll Wrld", name);
}
}

Pay extra attention to this line:

"Hello World".use(MyStringUtils.class).removeVowels();

What's more: this use of extensions doesn't have name spacing issues, nor does it pollute all of your objects. It's IDE friendly supporting both code completion and quick fixes!

As a side note, if generics were done better, I would like it to be:

"Hello World".use<MyStringUtils>().removeVowels();

But this is available now! I'll blog more on it tomorrow, but I am very excited about it.

5 comments:

Abe said...

I would recommend the use of the bootclasspath argument in java, than to override the files in the rt.jar.

http://java.sun.com/javase/6/docs/technotes/tools/windows/java.html

Anonymous said...

Okay, this is cool.

Now, can we get it added to the official java distro? :)

Unknown said...

Not to be a downer -- but for me this solution (while very clever and cool in terms of how its implemented) fails usability requirements for extensions methods, for two reasons:

* You can't access the non-extend method set AND the extended method set through the same object reference. So, for example, you couldn't easily make a fluent API by extending an existing fluent API.

* Extension classes are not composable. That is, you can't extend an already-extended object reference. So if you have 2 String extension classes, you could add both of them to the same String reference to get a superimposition of the two extending method sets.

Without both features, it feels like the syntax would end up having limited utility.

Unknown said...

If this is interesting to any reader, though, then he should take a look at either Groovy, which has dynamic/runtime extension capabilities, or Scala, which has static/compile-time extension capabilities. Both languages compile down to Java VM bytecodes.

Llewellyn Falco said...

Brian,

In general I agree with you, which is why i haven't made much use of it for the last year, however, now that I have lambdas, the importance has become much stronger, and i find my self needing it for linq like queryies.