2010-03-09 6 views
5

Je travaille avec Google Web Toolkit et j'ai des problèmes pour implémenter une interface générique. Je ne connais pas vraiment les génériques, je fais une mise à jour du code de quelqu'un d'autre ici.Sous-classes d'une classe qui implémente une interface générique

Voici ce que je veux faire: Je veux avoir une implémentation d'une interface de rappel générique qui fait de la journalisation, puis sous-classer cette implémentation afin de gérer des scénarios de rappel spécifiques.

L'interface est quelque chose comme ceci:

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

Les implémentations abstraites et concrètes ressembler à quelque chose comme ceci:

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

Les callbacks doivent être tirés de

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

Et puis tout se réunit dans un appel qui ressemble à ceci:

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

Et voici où nous avons un problème!

Lorsque le GWT.create() implémente l'interface que j'ai créé, il exige que le type donné à AsyncCallback est spécifié (correspond à un type ailleurs, en dehors de la portée de cette question), ce qui rend DoSomething(AsyncCallback<Integer>) un entier plutôt que d'un objet. Ceci est hors de mon contrôle. Il se plaint que DoSomething() prend AsyncCallback<Integer>. Je lui donne quelque chose qui hérite de quelque chose qui est un AsyncCallback<Object>. Je suppose qu'avec les génériques, les concepts d'héritage sont quelque peu brisés?

Alors ma question est la suivante:

Soit comment puis-je mush cela ensemble pour que DoSomething() reconnaîtront que ce SpecificCallback répond qu'il est exigences,

ou comment puis-je structurer la relation entre CallbackBase et SpecificCallback de sorte que le code en double est évité, mais SpecificCallback implémente AsyncCallback<Integer> directement?

Merci.

Répondre

9

Ce que je pense que vous devez faire est de définir CallbackBase comme ceci:

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

Ensuite, vous voulez que vos callbacks spécifiques comme ceci:

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

Ensuite, votre méthode DoSomething, qui accepte une AsyncCallback<Integer>, acceptera un SpecificCallback.

(Pédant sidenote: s'il vous plaît toutes les méthodes avec commencer des lettres minuscules en Java)

Modifier

Pour ce que ça vaut, je vous suggère de changer votre conception à utiliser la composition plutôt que l'héritage. Dans ce cas, plutôt que d'utiliser une classe abstraite CallbackBase et de l'étendre, vous utiliseriez une mise en œuvre concrète de AsyncCallback<T> qui pourrait ressembler à ceci:

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

Beauté, merci! – Ipsquiggle

+0

Re: éditer. Oui, cela a beaucoup de sens. Je voulais l'adapter à quelque chose comme ça en premier lieu, mais je pensais que j'aborderais ma confusion un pas à la fois. ;) – Ipsquiggle

+0

Est-il possible d'étendre l'un ou l'autre pour tenir compte de deux types possibles? par exemple. conceptuellement équivalent à 'implémente AsyncCallback , AsyncCallback '? – Ipsquiggle

Questions connexes