2010-12-11 3 views
3

Est-il possible d'éviter le fouillis d'ajouter tous les types à la définition de classe lors de l'implémentation d'une interface comme celle-ci?Implémenter des méthodes génériques à partir d'une interface sans fouillis?

MyInterface.java

import java.util.List; 
abstract class BaseA {} 
abstract class BaseB {} 
abstract class BaseC {} 

interface MyInterface<T extends BaseA, U extends BaseB, V extends BaseC> { 
    public void foo(List<? extends T> list); 
    public void bar(List<? extends U> list); 
    public void baz(List<? extends V> list); 
} 

MyImplementation.java

/* Some concrete implementations of the abstract classes used in the interface */ 
class A extends BaseA{} 
class B extends BaseB{} 
class C extends BaseC{} 

class MyImplementation implements MyInterface<A,B,C> { 
    public void foo(List<? extends A> list){} 
    public void bar(List<? extends B> list){} 
    public void baz(List<? extends C> list){} 
} 

Ce que je n'aime pas à ce sujet est ce genre de choses que je trouve être méthode spécifique, tel que le type de paramètres, est mélangé avec la déclaration de classe. Comme dans ce cas, où je pour chaque méthode générique dans l'interface doit ajouter un type formel dans "la section de support". Y a-t-il une autre façon de réaliser ce qui précède (forçant un appelant de l'implémentation à utiliser une sous-classe spécifique de la classe de paramètres dans l'interface) sans tout le "fouillis"?

Je ne suis pas trop dans les génériques, et le code ci-dessus est fondamentalement basé sur une réponse à cette question.

+0

Si quelqu'un se demande à quoi sert une construction comme cela pourrait avoir, il est conseillé de consulter la dernière réponse ici: http://stackoverflow.com/questions/239645/overriding -a-method-with-generic-parameters-in-java Le code ci-dessus fonctionne comme prévu, je voulais juste voir s'il y a un autre moyen d'y parvenir sans toute la syntaxe supplémentaire. – oligofren

Répondre

1

Voici comment les génériques fonctionnent, cependant si vous ajoutez une longue liste de types, vous pourriez reconsidérer votre conception. Je dans ce cas (sans vraiment connaître le but de votre code), généralise l'interface un peu plus:

abstract class PlayBase {} 
interface MyInterface<T extends PlayBase> { 
    public void playWith(List<T> list); 
} 

... et un exemple d'implémentation:

class A extends PlayBase {} 
class MyImplementationA implements MyInterface<A> { 
    public void playWith(List<? extends A> list){} 
} 

De cette façon, la conception est beaucoup plus ouvert au changement de types d'une manière agréable (pas besoin de changer l'interface).

+0

L'utilisation de playWithA/B/C était un mauvais choix pour le nom de la fonction. Désolé pour ça. Ils n'étaient pas censés avoir quelque chose en commun, juste quelques noms de fonctions aléatoires. Edité la réponse pour refléter cela en utilisant les noms plus communs "aléatoires" de foo, bar, baz :) – oligofren

0

Que diriez-vous ceci:

interface MyInterface { 
    public <T extends BaseA> void playWithA(List<? extends T> list); 
    public <U extends BaseB> void playWithB(List<? extends U> list); 
    public <V extends BaseC> void playWithC(List<? extends V> list); 
} 
+0

C'est ainsi que j'ai essayé de l'implémenter au début, mais cette interface ne peut pas atteindre les objectifs énoncés ci-dessus. – oligofren

+0

(suite) En raison de l'effacement du type, vous ne pouvez pas implémenter MyInterface en tant que: class MyImpl { public void playWithA (Liste liste); ... etc } Ainsi, MyImpl.playWitA() devrait accepter toute liste de sous-classes de BaseA, et pas seulement A (qui était un objectif déclaré). – oligofren

Questions connexes