У меня есть интерфейс:
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>)
Разве это не должно работать, если это соединяет интерфейсом с тем классом?
Возможно, вам понадобится
public void sendNotification( Class<? extends IMech> mechanism ) {
Поскольку два класса Class
и Class
сами по себе не связаны по наследству, хотя IMechanism
и EmailNotification
- это .
Вам нужно, чтобы ваш метод принимал Class расширяет IMechanism>
.
Универсальные шаблоны не работают в Java. Что вам действительно нужно сделать, это изменить сигнатуру метода на
public void sendNotification( Class< ? extends IMech > mechanism ){
}
Или super
вместо extends
... позвольте мне проконсультироваться с главой Generics по Эффективной Java ...
Редактировать: Эффективная Java говорит:
Вот мнемоника, которая поможет вам запомните, какой тип подстановочного знака использовать: PECS расшифровывается как «производитель-расширяет», «потребитель-супер».
Я предполагаю, что это будет создавать экземпляры IMech, и что extends
верно.
Ваш механизм параметров должен использовать ограниченный подстановочный знак, как например:
public void sendNotification( Class< ? extends IMech > mechanism ){ }
Цитирую учебник по дженерикам текст ссылки
В общем случае, если Foo является подтипом (подкласс или субинтерфейс) Bar, и G - это некоторое объявление общего типа, то не факт, что G является подтипом G.
Идея интерфейсов заключается в том, что вам не нужно знать, какой именно. Вы должны просто иметь возможность передавать 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);
Теперь я знаю, что они не дают прямого ответа на ваши вопросы, но это типичные формы использования, которые обычно указывают на более гибкие шаблоны проектирования. В конце концов, вам действительно нужно отправлять объект класса? Перечисление кажется более подходящим, если вы просто определяете, какой механизм использовать.