Фон
Я пытался использовать Обработчики аннотации, чтобы генерировать реализации конкретных интерфейсов Factory. Эти интерфейсы выглядят следующим образом:
public interface ViewFactory<T extends View> {
<S extends Presenter<T>> T create(S presenter);
}
а также
public interface PresenterFactory<T extends View> {
<S extends Presenter<T>> S create();
}
Обработчик аннотации делает правильную вещь и генерирует фабрику для каждого соответствующего класса, который аннотируется соответствующей аннотацией.
Эта проблема
Выходной сигнал обработчика аннотаций следующий:
public final class TestViewImplFactory implements ViewFactory {
public final TestView create(TestPresenter presenter) {
return new TestViewImpl(presenter);
}
}
и соответствующий другой класс:
public final class TestPresenterImplFactory implements PresenterFactory {
public final TestPresenter create() {
return new TestPresenterImpl();
}
}
Однако TestViewImplFactory не может быть скомпилирован. Сообщение об ошибке:
"Класс" TestViewImplFactory "должен быть объявлен абстрактным или реализовать абстрактный метод create (S) в" ViewFactory ""
Java говорит, что верно следующее:
@Override
public View create(Presenter presenter) {
return new TestViewImpl(presenter);
}
который не будет работать вообще, учитывая, что пользователь хочет знать, какой вид будет возвращен и какой докладчик требуется. Я бы ожидал, что:
- либо оба автогенерированных файла ошибочны
- или оба правильные
потому что они оба очень похожи. Я ожидал, что первое будет правдой.
Что мне здесь не хватает?
Если я добавлю тип Generic в TestViewImplFactory следующим образом:
public final class TestViewImplFactory implements ViewFactory<TestView> {
@Override
public <S extends Presenter<TestView>> TestView create(S presenter) {
return new TestViewImpl(presenter);
}
}
Возникает проблема, что параметр конструктора (который относится к типу TestPresenter) неверен. Изменение S на конкретный TestPresenter снова сделает класс не компилируемым по той же причине, что и выше.
Итак, я наткнулся на "решение", которое можно скомпилировать.
Что в основном должно быть сделано, это изменить интерфейс ViewFactory на следующее:
public interface ViewFactory<T extends View, S extends Presenter<T>> {
T create(S presenter);
}
Таким образом, определение класса имеет тот же общий тип, что и метод в Вопросе выше.
После компиляции (на этот раз с типичной спецификацией типа) вывод выглядит следующим образом:
public final class TestViewImplFactory implements ViewFactory<TestView, TestPresenter> {
public TestViewImplFactory() {
}
public final TestView create(TestPresenter presenter) {
return new TestViewImpl(presenter);
}
}
Это можно скомпилировать и выполнить успешно.
Это, однако, не отвечает на исходный вопрос. Почему родовое явно указано в правильности определения типа, но унаследовано и указано в объявлении метода неправильно и не компилируется?
Чтобы быть конкретным: почему Java может наследовать один Generic автоматически (внутри PresenterFactory), а другой нет (в ViewFactory, при методе и в объявлении типа)?