Передача класса интерфейса в качестве параметра в Java - PullRequest
33 голосов
/ 18 мая 2010

У меня есть интерфейс:

public interface IMech {

}

и класс, который его реализует

public class Email implements IMech {

}

и третий класс, в котором реализован этот метод:

public void sendNotification( Class< IMech > mechanism ){
}

сейчас я пытаюсь вызвать этот метод примерно так

foo.sendNotification(Email.class);

но я получаю исключение, говорящее:

The method sendNotification(Class<IMech>) in the type RemediationOperator is not applicable for the arguments (Class<Email>)

Разве это не должно работать, если оно взаимодействует с этим классом?

Ответы [ 7 ]

48 голосов
/ 18 мая 2010

Возможно, вам нужно

public void sendNotification( Class<? extends IMech> mechanism ) { 
10 голосов
/ 18 мая 2010

Поскольку два класса Class<IMechanism> и Class<EmailNotification> сами по себе не связаны наследованием, хотя IMechanism и EmailNotification являются .

Вы должны заставить свой метод принимать Class<? extends IMechanism>.

5 голосов
/ 18 мая 2010

Механизм параметров должен использовать ограниченный подстановочный знак, например:

public void sendNotification (механизм Class <? Extends IMech>) { }

Цитирование универсального учебника текст ссылки

В общем, если Foo является подтипом (подкласс или подинтерфейс) Bar, и G - это некое обобщенное объявление типа, оно это не тот случай, когда G является подтип G.

3 голосов
/ 03 сентября 2012

правильный путь:

public void sendNotification(IMech mechanism) {

}

, поэтому, пожалуйста, прочитайте некоторые Java-учебники об интерфейсах для всех!

3 голосов
/ 18 мая 2010

Обобщения не работают таким образом в Java. Что вам действительно нужно сделать, это изменить сигнатуру метода на

public void sendNotification( Class< ? extends IMech > mechanism ){
}

Или это super вместо extends ... позвольте мне обратиться к главе Generics Effective Java ...

Edit: Эффективная Java говорит:

Вот мнемоника, чтобы помочь вам помните, какой тип подстановочного знака использовать: PECS расшифровывается как производитель расширяет, потребитель супер.

Я предполагаю, что это будет создавать экземпляры IMech, и что extends является правильным.

1 голос
/ 22 сентября 2012

IMO было бы чище, если бы вы сделали это:

public void sendNotification( IMech mechanism ){
}

Вы всегда можете получить класс внутри метода.

1 голос
/ 18 мая 2010

Идея интерфейсов в том, что вам не нужно знать, какой это. Вы должны просто иметь возможность передавать IMech и вызывать его функциональность независимо от реализации. Учтите следующее:

public interface IMech {
    void sendMessage();
}

public class Email implements IMech {
    @Override
    void sendMessage() { /* stuff here to send email */ }
}

Это типичная схема использования интерфейса. Если вы используете его только для опции, возможно, вам следует рассмотреть возможность использования перечисления.

enum IMech { EMAIL, INSTANT_MESSAGE, SNAIL_MAIL, YELL_OVER_CUBICLE }

public void sendNotification( IMech mechanism ){
    switch(mechanism) {
        case IMech.EMAIL: // do email .. etc
    }
}

foo.sendNotification(IMech.EMAIL);

Теперь я знаю, что они не отвечают непосредственно на ваши вопросы, но это типичные формы использования и обычно указывают на более адаптируемые шаблоны проектирования. В конце концов, вам действительно нужно отправить объект класса? Перечисление кажется более подходящим, если вы просто определяете, какой механизм использовать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...