2012-01-12 73 views
2

所以,是的,我見過this question。但是,如果我有兩個接口,IAIB,但我想一個參數的函數(或類的屬性)是:如何將變量類型設置爲「實現這兩個接口的東西」?

public void (<? extends IA, IB> someClass) { 
//... 
} 

有沒有辦法做到這一點,而不使用泛型?

編輯:

我已經意識到我真正想要的是Duck Typing,如同在Python。我只是沒有把我的話說清楚。考慮到這一點,顯然在Java中沒有真正的方法來做到這一點。我接受this answer,但後來意識到輸入必須具有新的interface的簽名才能工作。但是,他確實符合我的尷尬措辭標準:)。

+0

目前您的鏈接去同一個問題,就是你故意的嗎? – 2012-01-12 21:53:40

+0

@CrazyJugglerDrummer啊不,我不打算,謝謝! – daveslab 2012-01-12 23:29:37

回答

5
interface IAandIB extends IA, IB { } 

public void Foo(IAandIB someClass) { 
//... 
} 

由於接口可以擴展多個其他接口,你可以做一個空的「虛擬接口」擴展他們兩人,並用它作爲類型,只要兩者都需要進行指定。

這工作,但它需要你修改實現IAIB,使他們能夠對這種方法,這是惱人的最好的,在某些情況下是不可能的工作,每一個類不是一個包羅萬象的解決方案。不幸的是,我不知道有沒有其他的方法來做到這一點沒有泛型。

+3

我認爲這是不對的。原始海報想要一個方法,其參數是任何實現了IA類的對象,並且還實現了IB。一般來說,這樣的類不會實現IAB,所以對象將不能被傳遞給這個方法。如果我誤解了你的答案,請糾正我。 – 2012-01-12 21:57:44

+0

@DavidWallace你可以理解,這個解決方案並不理想,因爲它需要修改所有可能傳遞給方法的潛在類。我不知道是否有其他方法可以做到這一點(沒有泛型),但是我遠離Java的專家,如果有更好的解決方案,我會很樂意提高它的效率,並在必要時刪除這個答案。 :D – 2012-01-12 22:07:16

+0

@CrazyJugglerDrummer有一種方法可以做到這一點,請參閱我的答案。 – Jesper 2012-01-12 22:08:03

6

該語法同樣適用於你想傳遞的東西成一個方法實現兩個接口IAIB

public <T extends IA & IB> void someMethod(T arg) { 
    // ... 
} 

對於一類的成員變量:

public class Example<T extends IA & IB> { 
    private T value; 

    // ... 
} 

(爲什麼你想這樣做沒有泛型?)。

+0

如果想要多次調用'someMethod'存儲傳入的'arg'值,所有這些值都實現IA和IB,但可能沒有公共基類型,以這種方式可以稍後傳遞給具有類似約束的例程。如果不能修改IA,IB可能會做的最好,IB可能通過調用抽象虛擬方法和派生的具體通用代理類來定義一個實現IA和IB的抽象代理類,派生實體通用代理類包含約束泛型類型的實例並實現通過在該實例上調用接口的方法。 – supercat 2012-01-12 22:29:17

+0

這種方法的問題是存儲的對象不會是傳入的對象,並且將無法以滿足通用約束的方式檢索傳入對象。 – supercat 2012-01-12 22:30:47

+0

有沒有辦法做到這一點,而不使用'T'?原因是我沒有那麼多地將它用作函數的參數,因爲我在一個類屬性上,並且我不能擁有一個沒有類行聲明它的引用'T'的類屬性。 – daveslab 2012-01-12 23:34:23

1

擴展CrazyJugglerDrummer's answer

interface IAandIB extends IA, IB { } 


public void Foo(IA a , IB b) 
{ 
    if (a != b) 
    { 
     throw new IllegalArgumentException () ; 
    } 
    ClassLoader loader = IAandIB . class . getClassLoader () ; 
    Class <?> [ ] interfaces = new Class <?> [ IAandIB . class , IA . class , IB . class ] ; 
    InvocationHandler handler = new InvocationHandler () 
    { 
      public Object invoke (Object proxy , Method method , Object [ ] args) throws Exception 
      { 
       Object r = null ; 
       try 
       { 
         // since a==b, it should not matter whether we use a or b here. 
         r = method . invoke (a , args) ; 
       } 
       catch (InvocationTargetException cause) 
       { 
         throw cause . getCause () ; 
       } 
       catch (Exception cause) 
       { 
         throw new RuntimeException (cause) ; 
       } 
      } 
    } 
    IAandIB ab = (IAandIB) (Proxy . newProxyInstance (loader , interfaces , handler)) ; 
    Foo (ab) ; 
} 

public void Foo(IAandIB someClass) { 
//... 
} 
+0

很酷,我沒有想到重載方法的方式來允許它被這樣調用。註釋行上有什麼代碼? – 2012-01-13 21:47:10

+0

@CrazyJugglerDrummer我添加了代理代碼 – emory 2012-01-13 23:49:58

相關問題