Я работаю с 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>
непосредственно?
Спасибо.
Я думаю, вам нужно определить 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);
}
}