簡體   English   中英

兩個接口指定具有相同簽名的方法,但指定具有不同的行為?

[英]Two interfaces specify methods with the same signature, but specified to have different behavior?

我有一些類public class myClass implements A, B ,其中A和B都包含一個方法public int doSomething(); ,但是A.doSomething由界面指定做與B.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; }
}

聲明一個名為getNumberOfScales的方法是不可能的 ,其簽名和返回類型與接口Fish和接口StringBass中聲明的方法兼容,因為一個類不能有多個具有相同簽名和不同原始返回類型的方法(§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();
    }
}

然后你的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對象。 我不確定它是否如何工作,所以這需要進行測試。

如果你重載方法,它是唯一可能的(不同的返回類型)

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;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM