607 Stimmen

Können Enums untergeordnet werden, um neue Elemente hinzuzufügen?

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?

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.

4voto

user2543191 Punkte 41

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.

4voto

Guillaume Robbe Punkte 548

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.

2voto

dsummersl Punkte 6228

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:

  • Sie möchten einige verwandte Enum-Codes haben, aber in unterschiedlichen Klassen. In meinem Fall hatte ich eine Basisklasse mit mehreren Codes, die in einem zugehörigen Enum definiert waren. Zu einem späteren Zeitpunkt (heute!) wollte ich der Basisklasse neue Funktionalitäten hinzufügen, was auch neue Codes für das Enum bedeutete.
  • Die abgeleitete Klasse würde sowohl das Enum der Basisklasse als auch ihr eigenes unterstützen. Keine duplizierten Enum-Werte! Also: Wie kann man ein Enum für die Unterklasse haben, das die Enums ihres Elternteils sowie ihre eigenen neuen Werte enthält.

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...

0voto

Matthias Ronge Punkte 8421

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.com

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.

Powered by:

X