Попытка построить расширяемый объект данных и шаблон адаптера в Java - PullRequest
0 голосов
/ 11 ноября 2011

Я пытаюсь собрать SDK, используя шаблон адаптера.Вот то, что я получил до сих пор:

interface Adapter<T> {
  void doWork(WorkUnit<T> unit);
  Class<T> getT();
}

class WorkUnit<T> {
  public int getId() { ... }
  public T getExtras() { ... }
}

class OldWorkUnit {
  public <T> void setExtra(T data) { /* Store data in Map<Class, Object> */ }
  public <T> WorkUnit<T> toNewWorkUnit(Adapter<T> adapter) { /* Map.get(adapter.getT()) */ }
}

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

Теперь я хочу взятьэто и вызвать doWork с WorkUnit.Мой первый проход по коду выглядит так:

class FooAdapter implements Adapter<FooWorkUnit> {
  ...
}

OldWorkUnit w = new OldWorkUnit();
w.setExtra(new FooWorkUnit());

Adapter<?> a = new FooAdapter();
WorkUnit<?> unit = w.toNewWorkUnit(a);

a.doWork(unit);

Ой, это не компилируется:

The method doWork(WorkUnit<capture#2-of ?>) in the type Adapter<capture#2-of ?> 
is not applicable for the arguments (WorkUnit<capture#4-of ?>)

Я знаю, что универсальный аргумент WorkUnit того же типа, что иAdapter.doWork () универсальный аргумент, но не зная типа, я не могу привести его соответствующим образом.

Так есть ли способ пройти через это?

1 Ответ

1 голос
/ 11 ноября 2011

Почему вы подстановили шаблон здесь?

Adapter<?> a = new FooAdapter();
WorkUnit<?> unit = w.toNewWorkUnit(a);

Если вы сделаете это:

Adapter<FooWorkUnit> a = new FooAdapter();
WorkUnit<FooWorkUnit> unit = w.toNewWorkUnit(a);

Разве это не сохраняет то, что вам нужно?

Теперь компилятор знает, что FooWorkUnit является, так сказать, общим знаменателем.

Редактировать: Точка ОК, принятая об изменчивости времени выполнения. Как насчет строгой типизации метода, который выполняет эту работу, чтобы исключить подстановочные знаки, но при этом все же согласовываться:

@SuppressWarnings("unchecked")
public <X> void prepareArgsAndDoTheWork() {
    OldWorkUnit w = new OldWorkUnit();
    w.setExtra(new FooWorkUnit());

    Adapter<X> a = (Adapter<X>) ... ; // Obtain the Adapter by reflection etc 
    WorkUnit<X> unit = w.toNewWorkUnit(a);
    a.doWork(unit);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...