You might be able to use a Proxy
instance to do this. See this question for info on Proxy
(particularly, the second part of the answer.)
The InvocationHandler
that you write would check to see which interface is being used to call the method and delegate to the appropriate method inside your object. Here's what your implementation looks like:
public class MyClass {
// Note that we aren't implementing the interfaces anymore
public int doSomethingForA() {
return 0;
}
public int doSomethingForB() {
throw new IllegalArgumentException();
}
}
Then your InvocationHandler:
public class MyClassInvocationHandler implements InvocationHandler {
private MyClass target;
public MyClassInvocationHandler(MyClass target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
if (method.getDeclaringClass().equals(InterfaceA.class))
return MyClass.getMethod("doSomethingForA").invoke(target, args);
else if (method.getDeclaringClass().equals(InterfaceB.class))
return MyClass.getMethod("doSomethingForB").invoke(target, args);
else
throw new UnsupportedOperationException("Unsupported interface: " + method.getDeclaringClass());
} catch (NoSuchMethodException ex) {
throw new UnsupportedOperationException("Method not found", ex);
} catch (IllegalAccessException ex) {
throw new UnsupportedOperationException("Method was not public", ex);
} catch (InvocationTargetException ex) {
// May throw a NullPointerException if there is no target exception
throw ex.getTargetException();
}
}
}
Then to create the proxy, you'll pass in both interfaces:
Proxy.newProxyInstance(null, new Class<?>[] { InterfaceA.class, InterfaceB.class }, new MyClassInvocationHandler(mc));
I think this will work. When you call it using one interface or the other:
MyClass mc = new MyClass();
Object proxy = Proxy.newProxyInstance(null, new Class<?>[] { InterfaceA.class, InterfaceB.class }, new MyClassInvocationHandler(mc));
InterfaceA a = (InterfaceA) proxy;
a.doSomething();
InterfaceB b = (InterfaceB) proxy;
b.doSomething();
Then it should pass in Method
objects with different declaring classes. I'm not sure if this is how it works though, so this will need to be tested.