2010-03-09 20 views
5

Estoy trabajando con Google Web Toolkit, y tengo problemas para implementar una interfaz genérica. No estoy muy familiarizado con los genéricos, haciendo una actualización en el código de otra persona aquí.Subclases de una clase que implementa una interfaz genérica

Esto es lo que quiero hacer: quiero tener una implementación de una interfaz de devolución de llamada genérica que realice un registro y luego subclase esa implementación para manejar escenarios de devolución de llamada específicos.

La interfaz es algo como esto:

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

Las implementaciones abstractas y concretas ser algo como esto:

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 
    } 
} 

Se requieren las devoluciones de llamada para ser disparado desde

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

Y luego todo se une en una llamada que se ve así:

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

¡Y aquí es donde tenemos un problema!

Cuando el GWT.create() implementa la interfaz creé, exige que el tipo dado a AsyncCallback se especifica (coincide con un tipo en otros lugares, fuera del alcance de esta pregunta), por lo tanto haciendo DoSomething(AsyncCallback<Integer>) un entero en lugar de un objeto. Esto está más allá de mi control.

Se queja de que DoSomething() toma AsyncCallback<Integer>. Le doy algo que hereda de algo que es AsyncCallback<Object>. Supongo que con los genéricos, los conceptos de herencia se rompen un poco?

Así que mi pregunta es la siguiente:

De cualquier cómo puedo papilla esto juntos de manera que DoSomething() reconocerán que que SpecificCallback cumple es requisitos,

o cómo puedo estructurar la relación entre CallbackBase y SpecificCallback para evitar el código duplicado, pero SpecificCallback implementa AsyncCallback<Integer> directamente?

Gracias.

Respuesta

9

Lo que creo que hay que hacer es definir CallbackBase así:

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); 
    } 
} 

entonces usted quiere sus devoluciones de llamada específicos que ser así:

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

A continuación, el método DoSomething, que acepta una AsyncCallback<Integer>, aceptará un SpecificCallback.

(sidenote pedante: tiene que iniciar todos los métodos con letras minúsculas en Java)

Editar

Para lo que vale, me gustaría sugerir cambiar su diseño para utilizar la composición en lugar de herencia. En este caso, en lugar de utilizar una clase abstracta CallbackBase y extendiéndola, tendrá que utilizar una aplicación concreta de AsyncCallback<T> que podría ser algo como esto:

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); 
    } 
} 
+0

belleza, gracias! – Ipsquiggle

+0

Re: editar. Sí, eso tiene mucho sentido. Quería cambiarlo a algo así en primer lugar, pero pensé que abordaría mi confusión paso a paso. ;) – Ipsquiggle

+0

¿Es posible extender cualquiera de estos para tener en cuenta dos tipos posibles? p.ej. conceptualmente equivalente a 'implementa AsyncCallback , AsyncCallback '? – Ipsquiggle

Cuestiones relacionadas