我有一些类public class myClass implements A, B
,其中A和B都包含方法public int doSomething();
,但接口指定A.doSomething
来执行与B.doSomething
不同的操作。
我已阅读Two interfaces with same method signature implemented in Java class,但这并没有真正解决我的问题,因为方法被覆盖以执行相同的操作,但正如我上面所说,我的问题是关于何时在接口中指定它们做不同的事情。
例如,假设A.doSomething()
应该返回0
,而B.doSomething()
应该抛出异常,并且违反任何一个wold会导致应该采用它们的方法出现问题作为参数。
有没有办法在java中这样做?如果是这样,那怎么会这样做呢?
答案 0 :(得分:5)
根据JLS(这类似于您想要的情况,可能不完全正确)
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; }
}
不可能声明一个名为getNumberOfScales
的方法,其签名和返回类型与接口Fish和接口StringBass中声明的方法兼容,因为 a class不能有多个具有相同签名的方法和不同的原始返回类型(§8.4)。
除非您通过添加代理(或)方法签名来更改设计,否则无法执行您期望的操作。
答案 1 :(得分:1)
您可以使用Proxy
实例执行此操作。有关Proxy
的信息,请参阅this question(特别是答案的第二部分。)
您编写的InvocationHandler
将检查用于调用方法的接口,并委托给对象内的相应方法。以下是您的实现:
public class MyClass {
// Note that we aren't implementing the interfaces anymore
public int doSomethingForA() {
return 0;
}
public int doSomethingForB() {
throw new IllegalArgumentException();
}
}
然后你的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();
}
}
}
然后要创建代理,您将传入两个接口:
Proxy.newProxyInstance(null, new Class<?>[] { InterfaceA.class, InterfaceB.class }, new MyClassInvocationHandler(mc));
我认为这将有效。当您使用一个界面或另一个界面调用它时:
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();
然后它应该传递具有不同声明类的Method
个对象。我不确定它是否如何工作,所以这需要进行测试。
答案 2 :(得分:0)
如果你重载方法
,它是唯一可能的(不同的返回类型)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;
}
}