Как установить тип переменной как «нечто, реализующее эти два интерфейса»? - PullRequest
2 голосов
/ 13 января 2012

Итак, да, я видел этот вопрос . Однако, что если бы у меня было два интерфейса, IA и IB, но я хотел, чтобы параметр функции (или свойство класса) был:

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

Есть ли способ сделать это без использования дженериков?

EDIT:

Я понял, что мне действительно нужно Duck Typing , как в Python. Я просто не правильно сформулировал свои слова. Имея это в виду, очевидно, что нет реального способа сделать это в Java. Я принял этот ответ , но потом понял, что для ввода необходимо будет иметь подпись этого нового interface. Тем не менее, он действительно соответствовал моим неловко сформулированным критериям:).

Ответы [ 3 ]

6 голосов
/ 13 января 2012

Этот синтаксис работает для метода, в который вы хотите передать что-то, реализующее два интерфейса IA и IB:

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

Для переменной-члена класса:

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

    // ...
}

(Почему вы хотите сделать это без генериков?).

5 голосов
/ 13 января 2012
interface IAandIB extends IA, IB { }

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

Поскольку интерфейсы могут расширять несколько других интерфейсов, вы можете просто создать пустой «фиктивный интерфейс», который расширяет их оба, и использовать его в качестве типа для обозначения всякий раз, когда требуется оба.

Этоработает, но не является универсальным решением, так как требует, чтобы вы изменили каждый отдельный класс, который реализует IA и IB, чтобы они могли работать для этого метода, который в лучшем случае раздражает и невозможен в некоторых ситуациях.К сожалению, я не знаю другого способа сделать это без генериков.

1 голос
/ 13 января 2012

Расширение Ответ CrazyJugglerDrummer

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) {
//...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...