Ich möchte ein bereits vorhandenes enum nehmen und weitere Elemente wie folgt hinzufügen:
enum A {a,b,c}
enum B erweitert A {d}
/*B ist {a,b,c,d}*/
Ist dies in Java möglich?
Ich möchte ein bereits vorhandenes enum nehmen und weitere Elemente wie folgt hinzufügen:
enum A {a,b,c}
enum B erweitert A {d}
/*B ist {a,b,c,d}*/
Ist dies in Java möglich?
Als Hilfe zur Verständnis, warum das Erweitern eines Enums auf der Sprachebene nicht vernünftig ist, betrachten Sie, was passieren würde, wenn Sie eine Instanz des erweiterten Enums an eine Routine übergeben würden, die nur das Basis-Enum versteht. Ein Switch, bei dem der Compiler versprach, alle Fälle abgedeckt zu haben, würde tatsächlich nicht die erweiterten Enum-Werte abdecken.
Dies unterstreicht weiter, dass die Enum-Werte in Java keine Ganzzahlen sind wie in C: Um ein Java Enum als Array-Index zu verwenden, müssen Sie explizit nach seinem ordinal() -Element fragen. Um einem Java Enum einen beliebigen Ganzzahlwert zu verleihen, müssen Sie ein explizites Feld dafür hinzufügen und dieses benannte Element referenzieren.
Dies ist kein Kommentar zum Wunsch des OP, sondern zu warum Java es nie tun wird.
Ich schlage vor, den gegenteiligen Ansatz zu wählen.
Statt die bestehende Aufzählung zu erweitern, erstellen Sie eine größere und erstellen Sie ein Untersetzung davon. Zum Beispiel, wenn Sie eine Aufzählung namens PET haben und sie zu ANIMAL erweitern wollen, sollten Sie stattdessen dies tun:
public enum ANIMAL {
WOLF,CAT, DOG
}
EnumSet pets = EnumSet.of(ANIMAL.CAT, ANIMAL.DOG);
Seien Sie vorsichtig, pets ist keine unveränderliche Sammlung, Sie möchten vielleicht Guava oder Java9 für mehr Sicherheit verwenden.
Da ich selbst dieses Problem hatte, möchte ich meine Perspektive posten. Ich denke, dass es ein paar motivierende Faktoren gibt, um so etwas zu tun:
Die Verwendung eines Interface reicht nicht aus: Es können aus Versehen duplizierte Enum-Werte auftreten. Nicht wünschenswert.
Letztendlich habe ich einfach die Enums kombiniert: Dadurch wird sichergestellt, dass keine doppelten Werte vorhanden sein können, auf Kosten einer weniger engen Bindung an die zugehörige Klasse. Aber ich dachte, dass das Duplikat-Problem mein hauptsächliches Anliegen war...
Mein Weg, um den Code zu schreiben, wäre wie folgt:
// enum A { a, b, c }
static final Set enumA = new LinkedHashSet<>(Arrays.asList(new Short[]{'a','b','c'}));
// enum B extends A { d }
static final Set enumB = new LinkedHashSet<>(enumA);
static {
enumB.add((short) 'd');
// Wenn Sie weitere Elemente hinzufügen müssen:
// enumB.addAll(Arrays.asList(new Short[]{ 'e', 'f', 'g', '', '' }));
}
LinkedHashSet
stellt sicher, dass jeder Eintrag nur einmal vorhanden ist und dass ihre Reihenfolge erhalten bleibt. Wenn die Reihenfolge nicht wichtig ist, können Sie stattdessen HashSet
verwenden. Der folgende Code ist in Java nicht möglich:
for (A a : B.values()) { // enum B extends A { d }
switch (a) {
case a:
case b:
case c:
System.out.println("Der Wert ist: " + a.toString());
break;
default:
throw new IllegalStateException("Das sollte niemals passieren.");
}
}
Der Code kann wie folgt geschrieben werden:
for (Short a : enumB) {
switch (a) {
case 'a':
case 'b':
case 'c':
System.out.println("Der Wert ist: " + new String(Character.toChars(a)));
break;
default:
throw new IllegalStateException("Das sollte niemals passieren.");
}
}
Ab Java 7 können Sie dasselbe sogar mit String
machen:
// enum A { BACKWARDS, FOREWARDS, STANDING }
static final Set enumA = new LinkedHashSet<>(Arrays.asList(new String[] {
"BACKWARDS", "FOREWARDS", "STANDING" }));
// enum B extends A { JUMP }
static final Set enumB = new LinkedHashSet<>(enumA);
static {
enumB.add("JUMP");
}
Verwendung des Enum-Ersatzes:
for (String a : enumB) {
switch (a) {
case "BACKWARDS":
case "FOREWARDS":
case "STANDING":
System.out.println("Der Wert ist: " + a);
break;
default:
throw new IllegalStateException("Das sollte niemals passieren.");
}
}
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.
15 Stimmen
Ein Grund dafür ist, dies zu tun, ist das Testen der Situation, in der ein ungültiger Enum-Wert vorhanden ist, ohne einen ungültigen Enum-Wert im Kernquellcode einzuführen.
0 Stimmen
Ja, ein Beispiel für "linguistische" Reinheit. Ich denke, was gewünscht wird, ist die "buchhalterische" Arbeitserleichterungsidee eines automatisch inkrementierenden Satzes von Ganzzahlen wie man es in C++ hat, damit man einen neuen Satz als Erweiterung des alten Satzes beginnen kann, beginnend bei 1 + dem letzten Wert des vorherigen Satzes, und wenn die Einträge benannt sind, die Namen aus dem "gemeinsamen Subset" erben. Obwohl das Java Enum einige schöne Dinge an sich hat, fehlt ihm die einfache automatisierte Hilfe zur Deklaration von Auto-Inkrementierungsintegern, die C++ Enum bereitstellt.
5 Stimmen
Tatsächlich, wenn Sie Ihren Aufzählungstyp mit neuen Werten erweitern, erstellen Sie keine Unterklasse, sondern eine Oberklasse. Sie können überall die Basisenumwerte anstelle des „erweiterten“ Enums verwenden, jedoch nicht umgekehrt. Daher ist gemäß dem Liskovschen Substitutionsprinzip der erweiterte Aufzählungstyp die Oberklasse des Basisenums.
0 Stimmen
@Ilya ... ja, das ist wahr. Ich weise darauf hin, dass die Frage eindeutige praktische Anwendungsfälle hat. Um des Arguments willen, betrachten Sie einen Basisklasse-Enum von:
Primärfarben
; es ist vernünftig, dies zu einer Überklasse-EnumPrimär- und Pastellfarben
zu unterklasse durch Hinzufügen neuer Farbnamen. Liskov ist immer noch der Elefant im Raum. Also warum nicht mit einem Basisklasse-Enum von:AllMeineFarben
beginnen -- Und dann könnte man alle Farben zu:Primär- und Pastellfarben
unterklasse und anschließend diese zu:Primärfarben
unterklasse (unter Berücksichtigung der Hierarchie). Java erlaubt das jedoch auch nicht.