9
votes

Enums avec interface - comment faire de manière générique?

Si j'ai un ensemble d'énums, et que je veux les faire mettre en œuvre une interface, est-ce la bonne façon de faire de manière générique?

ENUM: P>

public class SkillsSet<T extends SkillType> {
    T t;
    Map<T,Integer> skills = new HashMap<>();
    public SkillsSet(String[] skills) {
        for (String string : skills) {
            addSkill(string,t.getUntrainedPenalty());
        }
    }
    private void addSkill(String skillString,Integer value) {
        skills.put((T) t.fromValue(skillString), 0);
    }
}


2 commentaires

Pourquoi ne pas passer dans un t [] au lieu d'une chaîne [] ?


Parce que je ne peux pas stocker T [] dans le fichier, mais je peux avec des chaînes dans un document texte.


4 Réponses :


1
votes

ici xxx

la valeur de la valeur (valeur) est une statique, elle n'est pas associée à une instance Enum, ce qui signifie que vous ne pouvez pas l'appeler génériquement. Ce que vous pouvez faire: xxx

ou plus clairement xxx

si vous envisagez d'avoir plus de types d'énumération qui implémentent SkillType Ensuite, vous avez besoin d'une usine sur ces types. Cependant, dans ce cas, Enum n'est probablement pas la meilleure décision de conception.


1 commentaires

Le problème avec ces "solutions" est que vous êtes câblé dans un spécifique . Je soupçonne qu'ils vous donneront des erreurs de compilation. Par exemple, mentalskill.values ​​() [0] donne un mentalskills , ce qui n'est pas nécessairement une instance du t que vous avez instancié < Code> Skillset avec,



2
votes

Le problème vient dans mon t T T qui donnera évidemment une NPE car je n'instancite pas mon type déduit. Le problème est que je ne peux pas, car c'est un énumé. P>

En fait, vous ne pouviez même pas si c'était une classe "régulière"! Il n'est pas possible de créer des instances d'un type de paramètre au sein d'une classe générique ... Sauf si vous ne passez pas dans un objet code> comme paramètre explicite. P>

dans le cas d'un Enum code>, vous devez soit transmettre une valeur du Enum code> ou transmettre la classe code> pour le Enum code> et utilisez le Enum .valueof (classe , chaîne) code> méthode pour faire une recherche. p>

quelque chose comme ça serait nécessaire .... p> xxx pré>

mais les compétences code> ne font pas beaucoup de sens pour moi. Pourquoi utiliseriez-vous la "pénalité non entraînée" pour une instance t code> pour initialiser la valeur de compétence de toutes les compétences? Cela a plus de sens si c'est quelque chose de plus comme ceci: p> xxx pré>

Vous instanceriez un Skillset code> comme ceci: P>

SkillSet<MentalSkill> st = new SkillSet<>(new String[]{"COMPUTER", "OCCULT"},
                                          MentalSkill.class);


4 commentaires

Cela semble plus prometteur que j'espérais!


@PureFerret - Vérifiez que tout cela compile. Si c'est le cas, je suis assez confiant que cela fonctionnera.


Ce code ne compile pas, mon Java / Eclipse ne reconnaît pas Enum (dans la ligne t t = ENUM .Valueof (Enumclass, chaîne) ), même si je suis explicitement Importez-le. Une idée de ce que ce serait?


Maintenant, la valeurOf se plaint d'une inadéquation liée. Type déduit T n'est pas un substitut valide du paramètre limité J'ai essayé d'autres orteils dans l'appel de la méthode et sur le type et rien ne semble "valide".



3
votes

Votre problème réside dans Stabilitype - il devrait être générique: xxx

Ceci s'appelle un auto référencage paramètre générique.

Sans cette auto-référence, vous pouvez renvoyer une instance de la classe différente à partir de la méthode fromvalue () .

Voici comment ça regarderait: xxx

et xxx

une fois que vous avez effectué ce changement, il devrait tous tomber en place.


2 commentaires

Cela semble mieux, mais cela ne fonctionnera pas même avec ce changement.


J'ai vu le modèle "Paramètre générique d'auto-référencement" utilisé mais je ne connaissais pas le nom pour cela.



2
votes

Une solution consiste à utiliser la réflexion. Je ne suis pas sûr s'il y a d'autres solutions qui pourraient avoir l'air plus propre. Ce qui suit est compilé et exécuté cependant. xxx

Il existe deux versions différentes de getenumvalue . Je recommanderais la version qui utilise la méthode getenumConstants sur le paramètre Enumclass . Il vous permet également de gérer des cas spéciaux dans devalue qui pourraient ne pas correspondre généralement à la fonction de l'ENum .

instantifiant les travaux ci-dessus avec Comformsetssets = Nouvelle compétence de compétence (nouvelle chaîne [] {"Ordinateur", "Artisanat"}, MentalSkill.class);


0 commentaires