2010-12-07 6 views
2

Pourriez-vous s'il vous plaît aidez-moi? Exemple de code:Java Générique wildcard étend problème

public abstract class AbstractWorker { 

    public abstract void execute(); 

} 

public class Config { 

    public final String name; 

    public Config(final String name) { 
     this.name = name; 
    } 

} 

public abstract class AbstractWorkerFactory<C extends Config> { 

    public abstract AbstractWorker createWorker(final C configuration); 

} 

public class Service { 

    public AbstractWorker caramba(final AbstractWorkerFactory<? extends Config> factory, final Config configuration) { 
     // it is not compile :(
     return factory.createWorker(configuration); 
    } 

} 

code suivant fonctionne

public <C extends Config> AbstractWorker caramba(final AbstractWorkerFactory<C> factory, final C configuration) { 
    return factory.createWorker(configuration); 
} 

Mais le code qui utilise le service ne pouvait pas spécifier le type générique. Est-il possible d'autre solution.
MISE À JOUR (après réponse par meriton):
1. L'usine de concentration et l'instance de configuration créent à différents endroits (classes).
2.

public static class MegoConfig extends Config { 

public static class WorkerFactory extends AbstractWorkerFactory<Config> { 

public static class MegoWorkerFactory extends AbstractWorkerFactory<MegoConfig> { 

MegoWorkerFactory support MegoConfig et Config.
Nouvelle solution pour ma tâche.

public AbstractWorker caramba(final AbstractWorkerFactory<? super MegoConfig> factory, MegoConfig configuration) { 
     return factory.createWorker(configuration); 
} 

new Service().caramba(new WorkerFactory(), new MegoConfig("")); 
new Service().caramba(new MegoWorkerFactory(), new MegoConfig("")); 

Un grand merci à tous pour votre réponse!

+2

Pourquoi le code qui utilise Service ne peut-il pas spécifier le type générique? Avait-il une AbstractWorkerFactory , ou était-ce Java 1.4? – ILMTitan

Répondre

3

La déclaration

public AbstractWorker caramba(final AbstractWorkerFactory<? extends Config> factory, final Config configuration) { 

est trop large; il accepte toute WorkerFactory avec n'importe quelle configuration, n'exprimant pas que chaque workerfactory attend une configuration spécifique. Autrement dit, il serait tout à fait légal d'écrire

caramba(new AbstractWorkerFactory<FooConfiguration>() { ... }, new BarConfig()); 

même si cette WorkerFactory ne peut pas fonctionner avec cette configuration.

D'autre part, la déclaration

public <C extends Config> AbstractWorker caramba(final AbstractWorkerFactory<C> factory, final C configuration) 

correctement exprime que le WorkerFactory fourni doit être compatiable avec la configuration fournie, au moyen de la même variable de type apparaissant dans les deux déclarations de paramètres.

Mais le code qui utilise Service n'a pas pu spécifier de type générique. Est-il possible d'autre solution?

Je ne comprends pas; pourquoi pas? Pourquoi avez-vous besoin d'une autre solution?

+0

Salut, Merci beaucoup pour votre réponse. J'ai mis à jour le post pour répondre à vos questions. –

0

Sont-ils tous dans le même fichier? Vous ne pouvez pas avoir plusieurs classes publiques dans un seul fichier source. Cela ne tient pas compte de l'erreur générique, cependant.

J'ai jeté ces derniers dans un fichier source avec votre classe Service, et a obtenu la compilation très bien:

class Config {} 
class AbstractWorker {} 
abstract class AbstractWorkerFactory<C extends Config> { 
    public abstract AbstractWorker createWorker(final C configuration); 
} 

Quel est le code qui utilise Service?

0

Non, la solution que vous fournissez est probablement le meilleur:

public <C extends Config> AbstractWorker caramba(final AbstractWorkerFactory<C> factory, final C configuration) { 
    return factory.createWorker(configuration); 
} 

Sinon, vous pouvez utiliser la signature première dans la méthode caramba, sans les jokers, mais cela apporterait d'autres problèmes, tels que les avertissements du compilateur.