Универсальный с аргументами типа переменной - PullRequest
8 голосов
/ 03 января 2012

Я хочу сделать что-то вроде

public interface Foo<R, P...> {
    public R bar(P...) {/*misc*/}
}

чтобы получить массив типов для использования в моей связанной реализации. Это возможно в Java?

Varargs позволяет мне иметь любое количество аргументов для данного класса.

Я хочу использовать его (или что-то подобное), чтобы мой метод принимал несколько аргументов, каждый из которых является членом данного другого класса. Эти классы определяются, когда родовой объект связан.

Я знаю, что есть обходные пути, но есть ли безопасный для типов способ сделать это?

Ответы [ 2 ]

7 голосов
/ 03 января 2012

Поскольку вы, очевидно, хотите, чтобы bar принимал несколько параметров разных типов (что-то, для чего не используются *), я бы предложил вместо этого принять единственный параметр. Затем вы можете сделать этот единственный параметр контейнером, который содержит каждый из отдельных «параметров», которые вы хотите использовать.

В общем, было бы лучше создать класс для каждого набора параметров, который вы хотите использовать с этим методом, чтобы у вас были хорошие имена для каждого из объектов, которые он содержит. Однако вы также можете сделать что-то вроде создания серии типов кортежей (например, Pair) для использования в качестве держателей.

Вот пример:

public class Foo<R, P> {
  /*
   * Not sure how you intend to provide any kind of implementation
   * here since you don't know what R or P are.
   */
  public R bar(P parameters) { ... }
}

public class SomeFoo extends Foo<SomeResult, Pair<Baz, Bar>> {
  public SomeResult bar(Pair<Baz, Bar> parameters) { ... }
}

SomeFoo foo = ...
SomeResult result = foo.bar(Pair.of(baz, bar));
2 голосов
/ 03 января 2012

Вы писали:

Я хочу использовать его (или нечто подобное), чтобы мой метод принимал несколько аргументов, каждый из которых является членом данного другого class.

Я не думаю, что это можно сделать безопасным для типов способом без каких-либо уродливых взломов, таких как включение экземпляра Class вместе с объектом.

Проблема в том, что с VarArgs вы фактически передаете массив.Но вы не можете иметь массив с различными типами объектов, все они должны быть одинаковыми (или подклассами, поэтому, если у вас есть X [] y, тогда каждый элемент должен быть подклассом X)

Если ваша функция действительно может работать с несколькими типами, вы можете создать что-то вроде класса, который хранит экземпляр Class вместе с экземпляром T и передачей в список аргументов var этого контейнера.

Так, например, у вас может быть

class TypedInstance<T>{
   Class<T> type;
   T instance;
}

, а затем функция, которая выглядит примерно так:

public whatever(TypedInstance<? extends Object>... whatever){
  ...
  doSomethingWith(whatever[0].type, whatever[0].instance);
  ...
}

Эти виды хаков необходимы из-за стирания типа Java,Универсальный параметр удаляется во время выполнения, поэтому, если вы хотите его использовать, вы должны вернуть его обратно.

...