Skip to content

Instantly share code, notes, and snippets.

@norswap
Created March 25, 2013 09:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save norswap/5236080 to your computer and use it in GitHub Desktop.
Save norswap/5236080 to your computer and use it in GitHub Desktop.
Multi.java (Multimethods in Java)
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