J'écris une bibliothèque, qui a un ensemble prédéfini de valeurs pour un enum. Disons, mon enum ressemble à celui ci-dessous.
public enum EnumClass {
FIRST("first"),
SECOND("second"),
THIRD("third");
private String httpMethodType;
}
Maintenant, le client qui utilise cette bibliothèque peut avoir besoin d'ajouter quelques valeurs supplémentaires. Disons que le client doit ajouter CUSTOM_FIRST
et CUSTOM_SECOND
. Cela n'écrase pas les valeurs existantes, mais donne l'énumération à 5 valeurs.
Après cela, je devrais pouvoir utiliser quelque chose comme <? extends EnumClass>
avoir 5 possibilités constantes.
Quelle serait la meilleure approche pour y parvenir?
Vous ne pouvez pas avoir un enum
étendre un autre enum
, et vous ne pouvez pas "ajouter" de valeurs à un enum
existant par héritage.
Cependant, enum
s peut implémenter interface
s.
Ce que je ferais, c’est que le enum
original mette en œuvre un marqueur interface
(c’est-à-dire, aucune déclaration de méthode), votre client pourrait alors créer son propre enum
en implémentant le même interface
.
Ensuite, vos valeurs enum
seront désignées par leur commun interface
.
Pour renforcer les exigences, vous pouvez demander à votre interface de déclarer les méthodes pertinentes, par exemple. dans votre cas, quelque chose dans les lignes de public String getHTTPMethodType();
.
Cela forcerait l'implémentation de enum
s à fournir une implémentation pour cette méthode.
Ce paramètre, associé à une documentation appropriée sur l'API, devrait permettre d'ajouter des fonctionnalités de manière relativement contrôlée.
Exemple autonome (ne vous occupez pas des noms paresseux ici)
package test;
import Java.util.ArrayList;
import Java.util.List;
public class Main {
public static void main(String[] args) {
List<HTTPMethodConvertible> blah = new ArrayList<>();
blah.add(LibraryEnum.FIRST);
blah.add(ClientEnum.BLABLABLA);
for (HTTPMethodConvertible element: blah) {
System.out.println(element.getHTTPMethodType());
}
}
static interface HTTPMethodConvertible {
public String getHTTPMethodType();
}
static enum LibraryEnum implements HTTPMethodConvertible {
FIRST("first"),
SECOND("second"),
THIRD("third");
String httpMethodType;
LibraryEnum(String s) {
httpMethodType = s;
}
public String getHTTPMethodType() {
return httpMethodType;
}
}
static enum ClientEnum implements HTTPMethodConvertible {
FOO("GET"),BAR("PUT"),BLAH("OPTIONS"),MEH("DELETE"),BLABLABLA("POST");
String httpMethodType;
ClientEnum(String s){
httpMethodType = s;
}
public String getHTTPMethodType() {
return httpMethodType;
}
}
}
sortie
first
POST
Les énumérations ne sont pas extensibles. Pour résoudre votre problème simplement
Enum.valueOf
: suit toutes les occurrences de la classe dans une carte statiquePar exemple:
public class MyType {
private static final HashMap<String,MyType> map = new HashMap<>();
private String name;
private String httpMethodType;
// replacement for Enum.valueOf
public static MyType valueOf(String name) {
return map.get(name);
}
public MyType(String name, String httpMethodType) {
this.name = name;
this.httpMethodType = httpMethodType;
map.put(name, this);
}
// accessors
public String name() { return name; }
public String httpMethodType() { return httpMethodType; }
// predefined constants
public static final MyType FIRST = new MyType("FIRST", "first");
public static final MyType SECOND = new MyType("SECOND", "second");
...
}
Pensez à Enum comme une classe finale avec des instances finales statiques. Bien sûr, vous ne pouvez pas étendre la classe finale, mais vous pouvez utiliser une classe non finale avec des instances finales statiques dans votre bibliothèque. Vous pouvez voir un exemple de ce type de définition dans JDK. La classe Java.util.logging.Level peut être étendue avec une classe contenant un ensemble supplémentaire de niveaux de journalisation.
Si vous acceptez ce mode d'implémentation, votre exemple de code de bibliothèque peut ressembler à:
public class EnumClass {
public static final FIRST = new EnumClass("first");
public static final SECOND = new EnumClass("second");
public static final THIRD = new EnumClass("third");
private String httpMethodType;
protected EnumClass(String name){
this.httpMethodType = name;
}
}
L'application client peut étendre la liste des membres statiques avec héritage:
public final class ClientEnum extends EnumClass{
public static final CUSTOM_FIRST = new ClientEnum("custom_first");
public static final CUSTOM_SECOND = new ClientEnum("custom_second");
private ClientEnum(String name){
super(name);
}
}
Je pense que cette solution est proche de ce que vous avez demandé, car toutes les instances statiques sont visibles depuis la classe client et qu'elles satisferont toutes à votre caractère générique générique.
Nous avons corrigé le problème d'héritage enum de cette façon, espérons que cela aide
Notre application a peu de classes et chacune a peu de vues enfants (vues imbriquées), afin de pouvoir naviguer entre les vues enfants et enregistrer la vue currentChildview, nous les avons enregistrées en tant qu'énum dans chaque classe. mais nous avons dû copier coller, quelques fonctionnalités communes comme next, previous et etc dans chaque énumération. Pour éviter que nous ayons besoin d'un BaseEnum, nous avons utilisé l'interface comme base de base:
public interface IBaseEnum {
IBaseEnum[] getList();
int getIndex();
class Utils{
public IBaseEnum next(IBaseEnum enumItem, boolean isCycling){
int index = enumItem.getIndex();
IBaseEnum[] list = enumItem.getList();
if (index + 1 < list.length) {
return list[index + 1];
} else if(isCycling)
return list[0];
else
return null;
}
public IBaseEnum previous(IBaseEnum enumItem, boolean isCycling) {
int index = enumItem.getIndex();
IBaseEnum[] list = enumItem.getList();
IBaseEnum previous;
if (index - 1 >= 0) {
previous = list[index - 1];
}
else {
if (isCycling)
previous = list[list.length - 1];
else
previous = null;
}
return previous;
}
}
}
et voici comment nous l'avons utilisé
enum ColorEnum implements IBaseEnum {
RED,
YELLOW,
BLUE;
@Override
public IBaseEnum[] getList() {
return values();
}
@Override
public int getIndex() {
return ordinal();
}
public ColorEnum getNext(){
return (ColorEnum) new Utils().next(this,false);
}
public ColorEnum getPrevious(){
return (ColorEnum) new Utils().previous(this,false);
}
}
vous pouvez aussi ajouter getNext/getPrevious à l'interface