Two interfaces define methods with the same signature, but are specified for different actions?

I have a class public class myClass implements A, B , where A and B contain the public int doSomething(); method public int doSomething(); , but A.doSomething is set by the interface to do something other than B.doSomething .

I read Two interfaces with the same method signature implemented in the Java class , but this does not really concern my problem, because the methods are reevaluated to do the same, but as I said above, my question is when they are specified in interfaces to do different things.

For example, suppose that A.doSomething() should return 0 , while B.doSomething() should throw an exception and violate either one reason caused by the reasons for methods that should treat them as parameters.

Is there any way to do this in java? If so, how do you actually do this?

+6
source share
3 answers

You might be able to use a Proxy instance for this. See this question for Proxy information (specifically, the second part of the answer.)

InvocationHandler you are writing will check to see which interface is used to invoke the method and delegate the corresponding 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 a proxy, you will go to both interfaces:

 Proxy.newProxyInstance(null, new Class<?>[] { InterfaceA.class, InterfaceB.class }, new MyClassInvocationHandler(mc)); 

I think it will work. When you call it using one interface or another:

 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 must pass Method objects with different declaration classes. I'm not sure how it works, so this will need to be tested.

+1
source

According to JLS (It looks like what you want, can't clarify)

 interface Fish { int getNumberOfScales(); } interface StringBass { double getNumberOfScales(); } class Bass implements Fish, StringBass { // This declaration cannot be correct, no matter what type is used. public ??? getNumberOfScales() { return 91; } } 

it is impossible to declare a method named getNumberOfScales whose signature type is compatible with the type of both methods declared in the Fish interface and in the StringBass interface, since a class cannot have several methods with the same signature and different primitive return types (ยง8.4).

If you do not change your design by adding the signature of the proxy method (or), you will not be able to do what you expect.

+4
source

This is only possible (different return types) if you overload the methods

 public interface IA { int doSomething(); } public interface IB { void doSomething(String value) throws Exception; } public class B implements IB, IA{ @Override public void doSomething(String value) throws Exception { throw new Exception(value); } @Override public int doSomething() { return 0; } } 
0
source

All Articles