#java #generics #inferred-type
#java #общие сведения #выводимый тип
Вопрос:
У меня есть метод, который возвращает сложный универсальный тип (который реализует несколько интерфейсов)
protected abstract <BOB extends Stan amp; Jan<I>> BOB getStanAndJanItem();
Это отлично компилируется, и я могу переопределить его и вернуть значения. Однако, как только я его вызываю, я получаю ошибки компиляции (его даже не нужно присваивать чему-либо). И я думаю, это имеет смысл, поскольку BOB определен только внутри метода.
Итак, как мне определить bob на уровне класса?
И ДА, я знаю, что могу просто разделить вызовы и заставить их возвращать один и тот же объект или ввести какое-то дополнительное наследование (и я, вероятно, в конечном итоге это сделаю), но можно ли это сделать и таким образом?
Получена ошибка:
Несоответствие привязки: универсальный метод getStanAndJanItem() типа MyAbstractClass<I>
неприменим для аргументов (). Предполагаемый тип Stan не является допустимой заменой для ограниченного параметра <BOB extends Stan amp; Jan<I>>
Комментарии:
1. Похоже, вы неправильно используете generics.
2. Можете ли вы опубликовать, как именно вы вызываете метод?
Ответ №1:
Чтобы вызвать метод, вам необходимо передать параметр универсального типа, который соответствует вашему ограничению.
Даже если вашему конкретному вызову это не нужно, вам все равно нужно передать параметр type.
Следовательно, вы можете вызвать метод, только если вы параметризуете его с помощью некоторого класса или интерфейса, который реализует оба этих типа.
Комментарии:
1. Я не совсем уверен, как это будет выглядеть. Я пытаюсь дублировать код типа — protected static <T extends Jan<I> amp; Stan> void do(T janAndStan, int id) — который отлично работает в качестве параметра
2. @rediVider:
something. <X> getStanAndJanItem()
, гдеX
реализованы оба интерфейса.3. я получил ‘Левая часть присваивания должна быть переменной’ при попытке присвоить ее <T extends Stan amp; Jan<I>> T bob или <T extends Stan amp; Jan<I>> bob
4.
<T extends Stan amp; Jan<I>>
это не тот тип, который вы можете использовать для объявления переменной.5. Хм .. интересно, возможно ли использование ‘var’ в . Net — это обходной путь для этого. Большое спасибо за быстрые ответы. Думаю, я продолжу с добавлением абстрактного потомка двух интерфейсов
Ответ №2:
Реальная проблема заключается в отсутствии поддержки типа пересечения. Предположим, язык поддерживает это напрямую, мы можем написать тип пересечения, подобный Aamp;B
etc, и ваш пример будет выглядеть следующим образом
Stanamp;Jan<I> getStanAndJanItem()
void setStanAndJanItem(Stanamp;Jan<I> item)
Stanamp;Jan<I> result = getStanAndJanItem();
result.doStanStuff();
result.doJanStuff();
setStanAndJanItem(result);
Без такой поддержки мы застряли. Ваше общее объявление, вероятно, неверно: оно подразумевает, что вызывающий определяет BOB
тип, в то время как вы, вероятно, хотите, чтобы BOB
тип определяла реализация. Реализация может возвращать все, что реализует оба Stan
и Jan<I>
. В настоящее время это требование не может быть выражено.
Комментарии:
1. Как я отметил в ответе на SLaks, у меня есть метод, который может налагать общие ограничения на его параметры [например, protected static <T расширяет Jan<I> amp; Stan> void do( T janAndStan, идентификатор int) ]. Я просто надеялся расширить это до возвращаемого типа. Мне кажется, что тот же механизм сработал бы и в этом случае, но, увы… Похоже, я ошибаюсь.