вернуть универсальный тип из универсальной функции - PullRequest
3 голосов
/ 26 мая 2009

у нас есть метод, более или менее похожий на следующий. однако в настоящее время мы возвращаем список которая в функции bla () вернет List<Bar> во время выполнения.

Я ищу способ сделать оба

List<Interface> =  troubleFuction(foo, bar.getCLass());;

и

List<Bar> = troubleFuction(foo, bar.getCLass());;

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

* Несоответствие типов: невозможно преобразовать из List<capture#3-of ? extends Bar> в List<Interface>*

есть ли способ сделать этот тип возврата возможным или стирание во время выполнения делает это невозможным

public <T1 extends Interface, T2 extends Interface> List<"problem"> troubleFunction( T1 in, Class<T2> clazz) {
  return in.doStuffWhichGeneratesAlistOF(clazz)
}

public void bla() {
  Foo foo = new Foo(); // implements interface
  Bar bar = new Bar(); // implements interface
  List<Interface> ifaces = toubleFuction(foo, bar.getCLass());
  List<Bar> mustAlsoWork = toubleFuction(foo, bar.getCLass());
}

редактирование: во многих существующих кодах метод вызывается как

List<Bar> result = troubleFunction(List<Interface> list, Bar.class);

таким образом, этот тип возврата должен оставаться совместимым (перезапись / перефакторинг не возможен)

по сути, я хочу, чтобы метод возвращал List <? super Bar>, если вызывается как

troublefunction(foo, Bar.class);

и List<? super Foo> при вызове

troublefunction(foo, Bar.class);

Ответы [ 4 ]

1 голос
/ 26 мая 2009

Вы не даете нам достаточно информации, чтобы действительно сказать, что вам нужно сделать. Например, вы не дали нам сигнатуру типа doStuffWhichGeneratesAlistOF() и не сказали нам, что она делает. И вы не сказали нам, что тип аргумента "in" имеет отношение ко всему этому.

Конечно, возможно , чтобы тип возвращаемого значения метода был универсальным. Например,

public <T extends Interface> List<T> troubleFunction(Interface in, Class<? extends T> clazz) {
  List<T> result = new ArrayList<T>();
  result.add(clazz.newInstance());
  return result;
}

И затем вы можете вызвать метод напрямую, как этот, и он будет работать (вам не нужно явно указывать параметр типа, потому что он выводится из присваивания):

List<Interface> iface = this.troubleFunction(foo, bar.getCLass());

Но, учитывая, как в приведенном выше коде вы возвращаете результат in.doStuffWhichGeneratesAlistOF(clazz), вам, вероятно, придется также сделать тип возвращаемого значения этого метода универсальным. Но я не могу вам в этом помочь, потому что у нас нет никакой информации об этом методе.

1 голос
/ 26 мая 2009

Вообще говоря, в подобных ситуациях вам необходимо явно передать объект Class в (параметризованный), который используется для возвращаемого значения.

Однако, похоже, вы уже сделали это в вашем случае, поэтому не сработает ли объявление troubleFunction о возвращении List<T2>? В качестве альтернативы, если вы хотите, чтобы оно было общим, верните его List<? extends Interface>.

0 голосов
/ 16 октября 2009

Я снова посмотрел на это, и проблема заключалась в том, что я хотел использовать возвращаемый тип 'super' подпись, которую я искал, была более или менее:

 public <T1 extends interface, T2 super T1> List<T2> getAList(Class<T1> clazz); 

что невозможно

0 голосов
/ 26 мая 2009

Насколько я понимаю, типы аргументов рассматриваются перед целевым типом, чтобы вывести общие аргументы. Итак, я думаю, вам нужно явно указать общие аргументы, которые, я думаю, выглядят примерно так:

List<Interface> iface = this.<Interface>troubleFunction(foo, bar.getCLass());

, где

public <T extends Interface> List<T> troubleFunction(
    T in, Class<? extends T> clazz
) {
...