2010-03-09 17 views
5

Sto lavorando con Google Web Toolkit e sto riscontrando problemi nell'implementazione di un'interfaccia generica. Non ho molta familiarità con i generici, faccio un aggiornamento sul codice di qualcun altro qui.Sottoclassi di una classe che implementa un'interfaccia generica

Ecco cosa voglio fare: voglio avere un'implementazione di un'interfaccia di callback generica che esegue alcuni logging e quindi sottoclassi quell'implementazione per gestire specifici scenari di callback.

L'interfaccia è qualcosa di simile:

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

Le implementazioni astratte e concrete simile a questa:

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

I callback sono tenuti ad essere licenziato da

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

E poi tutto si riunisce in una chiamata che assomiglia a questo:

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

Ed ecco dove abbiamo un problema!

Quando il GWT.create() implementa l'interfaccia ho creato, richiede che il tipo specificato AsyncCallback viene specificata (corrisponde a un tipo altrove, al di fuori dell'ambito della presente domanda), rendendo quindi DoSomething(AsyncCallback<Integer>) un intero piuttosto che un oggetto. Questo è al di fuori del mio controllo.

Si lamenta che DoSomething() prende AsyncCallback<Integer>. Sto dando qualcosa che eredita da qualcosa che è un AsyncCallback<Object>. Immagino che con i generici, i concetti di ereditarietà si rompano un po '?

Quindi la mia domanda è questa:

O come posso poltiglia questo insieme in modo che DoSomething() riconosceranno che che SpecificCallback soddisfa sia i requisiti,

o come posso strutturare il rapporto tra CallbackBase e SpecificCallback in modo che il codice duplicato venga evitato, ma SpecificCallback implementa direttamente AsyncCallback<Integer>?

Grazie.

risposta

9

Quello che penso che dovete fare è definire CallbackBase come questo:

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

Poi si desidera che il callback specifiche per essere come questo:

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

Poi il metodo DoSomething, che accetta un AsyncCallback<Integer>, accetterà uno SpecificCallback.

(sidenote Pedantic: si prega di avviare tutti i metodi con lettere minuscole in Java)

Modifica

Per quello che vale, io suggerirei di cambiare il vostro disegno di utilizzare composizione piuttosto che eredità. In questo caso, invece di usare una classe astratta CallbackBase ed estenderlo, utilizza un'implementazione concreta di AsyncCallback<T> che potrebbe essere simile a questa:

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

Bellezza, grazie! – Ipsquiggle

+0

Ri: modifica. Sì, questo ha molto senso. In primo luogo, volevo modificarlo in qualcosa del genere, ma ho pensato che avrei affrontato la mia confusione un passo alla volta. ;) – Ipsquiggle

+0

È possibile estendere uno di questi per tenere conto di due possibili tipi? per esempio. concettualmente equivalente a 'implementa AsyncCallback , AsyncCallback '? – Ipsquiggle

Problemi correlati