Monday, December 24, 2007

Implementing Closure without using inner classes

This implementation is inspired from Charles Nutters' discussion about his experiences implementing JRuby. I didn't have much time to look into it, until now. So here's my first implementation of it.

I have my Closure field a, and its body a_body.
In the Closure class, the ctor will reflectively get the declared method "a_body" by name.
When you'd like to invoke the closure, just call a.call(). Then it will normally invoke the "a_body" method with reflection.


package org.codehaus.qdg;

import org.codehaus.groovy.qdg.Closure;

public class TestGen_001 {

public Closure a = new Closure(this, "a_body");

private Object a_body(Object... args) {
System.out.println(args[0]);
System.out.println("a_body");
return null;
}

}



And here's a simple implementation of the class Closure:


package org.codehaus.groovy.qdg;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;

public class Closure {

private Object target;
private Method method;

public Closure(Object target, String methodName) {
this.target = target;
try {
method = target.getClass().getDeclaredMethod(
methodName, new Class[]{Object[].class});
AccessController.doPrivileged(
new PrivilegedAction(){
@Override
public Object run() {
method.setAccessible(true);
return null;
}
});
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}

public Object call(Object... args) {
try {
return method.invoke(target, (Object)args);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}



A closure body, which is a private method, is accessible by setting Method#setAccessible(true).

No comments: