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