Передача интерфейсного класса в качестве параметра в Java

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

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>)

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

34
задан Jarl 7 December 2012 в 10:55
поделиться

5 ответов

Возможно, вам понадобится

public void sendNotification( Class<? extends IMech> mechanism ) { 
49
ответ дан 27 November 2019 в 16:33
поделиться

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

Вам нужно, чтобы ваш метод принимал Class .

10
ответ дан 27 November 2019 в 16:33
поделиться

Универсальные шаблоны не работают в Java. Что вам действительно нужно сделать, это изменить сигнатуру метода на

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

Или super вместо extends ... позвольте мне проконсультироваться с главой Generics по Эффективной Java ...

Редактировать: Эффективная Java говорит:

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

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

3
ответ дан 27 November 2019 в 16:33
поделиться

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

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

Цитирую учебник по дженерикам текст ссылки

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

5
ответ дан 27 November 2019 в 16:33
поделиться

Идея интерфейсов заключается в том, что вам не нужно знать, какой именно. Вы должны просто иметь возможность передавать 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);

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

1
ответ дан 27 November 2019 в 16:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: