Vous trouverez ci-dessous une déclaration d'énumération valide.
public enum SomeEnumClass {
ONE(1), TWO(2), THREE(3);
private int someInt;
public SomeEnumClass(int someInt) {
this.someInt = someInt;
}
}
Mais puis-je remplacer une classe abstraite par un type enum?
SomeEnumClass.Java
public abstract enum SomeEnumClass {
private int someInt;
public SomeEnumClass(int someInt) {
this.someInt = someInt;
}
}
OverridingEnumClass.Java
public enum OverridingEnumClass extends SomeEnumClass {
ONE(1), TWO(2), THREE(3);
}
Sinon, pourquoi pas? Et quelle est une bonne alternative?
Non, tu ne peux pas; les types enum étendent tous Enum
, et ils sont implicitement final
. Les énumérations peuvent implémenter des interfaces, ou vous pouvez déclarer les méthodes pertinentes directement sur la classe d'énumération en question.
(Je vois l'idée de base de ce que vous voulez, qui est un mixin; peut-être que les interfaces Java 8 seront un peu plus utiles à cet égard.)
Dans Java vous ne pouvez pas étendre l'énumération ou créer une énumération abstraite ou même la générer. Si vous voulez avoir un point d'extension polymorphe sur votre énumération, vous pouvez appliquer un tel modèle.
Disons que votre énumération
public enum SomeEnumClass {
ONE, TWO, THREE;
}
Et vous voulez avoir un comportement associé à chaque valeur. Mais vous ne voulez pas coder en dur chacun, mais plutôt avoir la possibilité d'en fournir un autre. Vous devez donc déclarer l'interface
public interface SomeEnumVisitor<P, R> {
R one(P param);
R two(P param);
R three(P param);
}
Ajoutez ensuite une méthode abstraite à la déclaration d'énumération et à l'implémentation de cette méthode pour chaque valeur
public enum SomeEnumClass {
ONE {
@Override
public <R, P> R accept(SomeEnumVisitor<R, P> visitor, P param) {
return visitor.one(param);
}
}, TWO {
@Override
public <R, P> R accept(SomeEnumVisitor<R, P> visitor, P param) {
return visitor.two(param);
}
}, THREE {
@Override
public <R, P> R accept(SomeEnumVisitor<R, P> visitor, P param) {
return visitor.three(param);
}
};
public abstract <R, P> R accept(SomeEnumVisitor<R, P> visitor, P param);
}
Afin que vous puissiez créer une implémentation de visiteur pour étendre votre comportement d'énumération. Par exemple, dans votre cas, vous vouliez associer une valeur entière à chaque valeur énumérée.
public class IntValueVisitor implements SomeClassVisitor<Integer, Void> {
@Override
public Integer one(Void param){
return 1;
}
@Override
public Integer two(Void param){
return 2;
}
@Override
public Integer three(Void param){
return 3;
}
}
Et enfin, utilisez ce visiteur là où vous en avez besoin
SomeClassEnum something = getAnyValue();
// this expression will return your particular int value associated with particular enum.
int intValue = something.accept(new IntValueVisitor(), null);
Bien sûr, ce modèle s'applique s'il n'est pas approprié de tout déclarer à l'intérieur d'énum, par exemple si vous avez une déclaration d'énumération dans la bibliothèque et que vous souhaitez étendre le comportement d'énumération dans l'application principale. Ou vous ne voulez simplement pas coupler la définition d'énumération et les détails d'implémentation.
Afin de simplifier cette implémentation de modèle il existe une bibliothèque qui peut générer une énumération et un visiteur basés sur des annotations afin que tout ce que vous devez déclarer dans votre code soit
@AutoEnum(value = {"one", "two", "three"}, name = "SomeEnumClass")
public interface SomeEnumMarker {}
L'outil se reposera pour vous.
Si vous devez vraiment "étendre une énumération", vous pouvez utiliser le modèle d'énumération Typesafe pré-Java 1.5 (voir le bas de http://www.javacamp.org/designPattern/enum.html ) qui utilise en fait une classe, pas une énumération. Vous perdez la possibilité d'utiliser l'EnumSet avec vos "enum" et vous perdez certaines méthodes générées automatiquement telles que items (), mais vous avez la possibilité de remplacer les méthodes.
Un exemple:
// Typesafe enum pattern
public static abstract class Operator {
public static final Operator ADD = new Operator("+") {
@Override
public Double apply(Double firstParam, Double secondParam) {
return firstParam + secondParam;
}
};
public static final Operator SUB = new Operator("-") {
@Override
public Double apply(Double firstParam, Double secondParam) {
return firstParam - secondParam;
}
};
public static final Operator MUL = new Operator("*") {
@Override
public Double apply(Double firstParam, Double secondParam) {
return firstParam * secondParam;
}
};
public static final Operator DIV = new Operator("/") {
@Override
public Double apply(Double firstParam, Double secondParam) {
return firstParam / secondParam;
}
};
private static final Operator[] _ALL_VALUES = {ADD, SUB, MUL, DIV};
private static final List<Operator> ALL_VALUES = Collections.unmodifiableList(Arrays.asList(_ALL_VALUES));
private final String operation;
private Operator(String c) {
operation = c;
}
// Factory method pattern
public static Operator fromToken(String operation) {
for (Operator o : Operator.items())
if (o.operation.equals(operation))
return o;
return null;
}
public Iterable<Operator> items() {
return ALL_VALUES;
}
public abstract Double apply(Double firstParam, Double secondParam);
}