Подклассы класса, который реализует универсальный интерфейс

Я работаю с Google Web Toolkit, и у меня есть проблемы при реализации универсального интерфейса. Я не действительно знаком с дженериками, делая обновление на чужом коде здесь.

Вот то, что я хочу сделать: Я хочу иметь реализацию универсального интерфейса обратного вызова, который делает некоторый вход и затем разделяет ту реализацию на подклассы для обработки определенных сценариев обратного вызова.

Интерфейс - что-то вроде этого:

public interface AsyncCallback<T> {
    void MethodFromAsyncCallback(T result);
}

Абстрактные и конкретные реализации выглядят примерно так:

class CallbackBase implements AsyncCallback<Object> {
    public abstract void doStuff(Object result);

    public void MethodFromAsyncCallback(Object result) {
        // IMPORTANT STUFF
        // here are things I would like to do for all callbacks, hence the superclass.

        // Then we do the subclass specific things.
        doStuff(result);
    }
}

class SpecificCallback extends CallbackBase
{
    public void doStuff(Object result) {
        Integer i = (Integer)result;
        // do stuff with i
    }
}

Обратные вызовы требуются, чтобы быть запущенными из

public interface MyServiceAsync {
    public void DoSomeThing(AsyncCallback<Integer>);
}

И затем все это объединяется в вызове, который похож на это:

MyServiceAsync myService = (MyServiceAsync)GWT.create(MyServiceAsync.class);
myService.DoSomeThing(new SpecificCallback());

И вот то, где у нас есть проблема!

Когда GWT.create() реализует интерфейс, который я создал, он требует что тип, данный AsyncCallback указан (соответствует типу в другом месте, вне объема этого вопроса), следовательно делая DoSomething(AsyncCallback<Integer>) Целое число, а не Объект. Это находится вне моего контроля.

Это жалуется это DoSomething() берет AsyncCallback<Integer>. Я даю ему что-то, что наследовалось чему-то, что является AsyncCallback<Object>. Я предполагаю с дженериками, понятие наследования несколько повреждается?

Таким образом, мой вопрос - это:

Также, как может я шумы это вместе так, чтобы DoSomething() распознает это это SpecificCallback встречается это - требования,

или как я могу структурировать отношения между CallbackBase и SpecificCallback так, чтобы дублирующего кода избежали, но SpecificCallback реализации AsyncCallback<Integer> непосредственно?

Спасибо.

5
задан Ipsquiggle 9 March 2010 в 17:51
поделиться

1 ответ

Я думаю, вам нужно определить CallbackBase следующим образом:

abstract class CallbackBase<T> implements AsyncCallback<T> {
  public abstract void doStuff(T result);

  public void MethodFromAsyncCallback(T result) {
    // general stuff (T is a subclass of Object)
    doStuff(result);
  }
}

обратные вызовы должны быть такими:

class SpecificCallback extends CallbackBase<Integer> {
  public void doStuff(Integer result) {
    // no need to cast
    // do stuff with result
  }
}

Тогда ваш метод DoSomething , который принимает AsyncCallback , примет SpecificCallback .

(Педантичное замечание: пожалуйста, начинайте все методы в Java со строчных букв)

Редактировать

Что бы это ни стоило, я бы посоветовал изменить ваш дизайн, чтобы использовать композицию, а не наследование. В этом случае вместо использования абстрактного класса CallbackBase и его расширения вы должны использовать конкретную реализацию AsyncCallback , которая может выглядеть примерно так:

class GeneralCallbackWrapper<T> implements AsyncCallback<T> {
  private final AsyncCallback<? super T> delegate;

  public GeneralCallbackWrapper(AsyncCallback<? super T> delegate) {
    this.delegate = delegate;
  }

  public void MethodFromAsyncCallback(T result) {
    // general stuff here
    delegate.MethodFromAsyncCallback(result);
  }
}
10
ответ дан 13 December 2019 в 22:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: