Created
March 25, 2013 09:54
-
-
Save norswap/5236080 to your computer and use it in GitHub Desktop.
Multi.java (Multimethods in Java)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package util; | |
import java.lang.reflect.InvocationTargetException; | |
import java.lang.reflect.Method; | |
/** | |
* This class implements multiple dispatch (aka multimethods) using reflection. | |
* The idea is to choose the method based not only on the runtime type of the | |
* receiver, but also on the runtime type of the arguments. Normally Java | |
* selects amongst overloaded alternatives using the static type. | |
* | |
* The current version doesn't implement true multiple dispatch, as the system | |
* only searches for methods with the exact runtime parameters. See the | |
* dispatch() method for more details. The rationale is that I currently don't | |
* need more than that. | |
*/ | |
public class Multi | |
{ | |
/***************************************************************************** | |
* Tries to find a method of obj with the given name and whose parameter types | |
* are the types of the object in params. Beware that the search only | |
* considers the exact runtime type of the objects. e.g. a method taking an | |
* Object parameter won't be found when searching for a similarly named method | |
* taking a String parameter. | |
* | |
* To know which exceptions are thrown and when they arise, see the linked | |
* methods. | |
* | |
* @see Class#getMethod() | |
* @see Method#invoke() | |
*/ | |
public static Object dispatch(Object receiver, String name, Object... params) | |
throws NoSuchMethodException, SecurityException, IllegalAccessException, | |
IllegalArgumentException, InvocationTargetException | |
{ | |
Class<?>[] classes = new Class[params.length]; | |
int i = 0; | |
for (Object o : params) { | |
classes[i] = o.getClass(); | |
} | |
Method method = receiver.getClass().getMethod(name, classes); | |
return method.invoke(receiver, params); | |
} | |
/***************************************************************************** | |
* Optimized version of the dispatch() method, for methods of one argument. | |
*/ | |
public static Object dispatch1(Object receiver, String name, Object param) | |
throws NoSuchMethodException, SecurityException, IllegalAccessException, | |
IllegalArgumentException, InvocationTargetException | |
{ | |
Method method = receiver.getClass().getMethod(name, param.getClass()); | |
return method.invoke(receiver, param); | |
} | |
/***************************************************************************** | |
* A chill pill around dispatch(), turning all the check exceptions into a | |
* runtime exception. For when it should always work. | |
* @throws Throwable | |
* | |
* @see Multi#dispatch() | |
*/ | |
public static Object dynDispatch(Object receiver, String name, Object... params) | |
{ | |
try { | |
return dispatch(receiver, name, params); | |
} | |
catch (NoSuchMethodException | SecurityException | IllegalAccessException | |
| IllegalArgumentException e) | |
{ | |
e.printStackTrace(); | |
throw new RuntimeException("Illegal multimethod call."); | |
} | |
catch (InvocationTargetException e) | |
{ | |
throw new RuntimeException(e.getCause()); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment