如何将变量类型设置为“实现这两个接口的东西”?

时间:2012-01-12 21:45:42

标签: java interface

所以,是的,我见过this question。但是,如果我有两个接口IAIB,但我希望函数(或类的属性)的参数为:

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

有没有办法在不使用泛型的情况下执行此操作?

修改

我意识到我真正想要的是Duck Typing,就像在Python中一样。我只是没说出正确的话。考虑到这一点,显然在Java中没有真正的方法可以做到这一点。我接受了this answer,但随后意识到输入必须具有新interface的签名才能生效。但是,他确实符合我的措辞笨拙的标准:)。

3 个答案:

答案 0 :(得分:6)

此语法适用于您希望将某些内容传递到实现两个接口IAIB的方法:

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

对于类的成员变量:

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

    // ...
}

(为什么你想在没有泛型的情况下这样做?)。

答案 1 :(得分:5)

interface IAandIB extends IA, IB { }

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

由于接口可以扩展多个其他接口,因此您只需创建一个空的“虚拟接口”即可。它扩展了它们,并在需要时将其用作指定的类型。

这可行,但不是一个全能解决方案,因为它要求您修改实现IAIB的每个类,以便它们可以用于此方法,这最好是烦人的在某些情况下不可能。不幸的是,如果没有泛型,我不知道有任何其他方法可以做到这一点。

答案 2 :(得分: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) {
//...
}