Aufzählungen müssen nicht nur passive Mengen (z. B. Farben) darstellen. Sie können komplexere Objekte mit Funktionalität darstellen und so sind Sie dann wahrscheinlich weitere Funktionalität zu diesem hinzufügen wollen - zB Sie Schnittstellen haben können wie Printable, Reportableusw. und Komponenten , die diese unterstützen.
Hier ist ein Beispiel (ein ähnliches / besseres findet sich in Effective Java 2nd Edition):
publicinterfaceOperator{int apply (int a,int b);}publicenumSimpleOperatorsimplementsOperator{
PLUS {int apply(int a,int b){return a + b;}},
MINUS {int apply(int a,int b){return a - b;}};}publicenumComplexOperatorsimplementsOperator{// can't think of an example right now :-/}
So erhalten Sie eine Liste der beiden einfachen + komplexen Operatoren:
Hier verwenden Sie also eine Schnittstelle, um erweiterbare Aufzählungen zu simulieren (was ohne die Verwendung einer Schnittstelle nicht möglich wäre).
Komplexe Operatoren könnten "pow" und dergleichen sein.
Pimgd
2
Zum ersten Mal habe ich diese Enum-Syntax gesehen (mit den geschweiften Klammern nach den Mitgliedern), und ich programmiere seit 6 Jahren mit Java. Bis.
Jrahhali
23
Das ComparableBeispiel, das hier von mehreren Personen gegeben wurde, ist falsch, da dies Enumbereits umgesetzt wird. Sie können es nicht einmal überschreiben.
Ein besseres Beispiel ist eine Schnittstelle, die beispielsweise einen Datentyp definiert. Sie können eine Aufzählung zum Implementieren der einfachen Typen und normale Klassen zum Implementieren komplizierter Typen haben:
interfaceDataType{// methods here}enumSimpleDataTypeimplementsDataType{
INTEGER, STRING;// implement methods}classIdentifierDataTypeimplementsDataType{// implement interface and maybe add more specific methods}
Ja. Seltsam !!. Enum implementiert bereits die Schnittstelle Comparable und erlaubt kein Überschreiben. Ich habe den Java-Quellcode für die Enum-Klasse nachgeschlagen und konnte die compareTo-Implementierung nicht finden. Kann mir jemand sagen, was in einer compareTo-Methode mit einer ENUM verglichen wird?
AKh
2
@AKh vergleicht die Ordnungszahlen, was bedeutet, dass die natürliche Reihenfolge die Reihenfolge ist, in der sich die Enum-Konstanten in der Quelldatei befinden.
Jorn
Enum vars sind endgültig und so erfolgt der Vergleich mit ==, richtig?
Djangofan
@ Djangofan ja.
Jorn
17
Es gibt einen Fall, den ich oft benutze. Ich habe eine IdUtilKlasse mit statischen Methoden, um mit Objekten zu arbeiten, die eine sehr einfache IdentifiableSchnittstelle implementieren:
publicinterfaceIdentifiable<K>{
K getId();}publicabstractclassIdUtil{publicstatic<T extendsEnum<T>&Identifiable<S>, S> T get(Class<T> type, S id){for(T t : type.getEnumConstants()){if(Util.equals(t.getId(), id)){return t;}}returnnull;}publicstatic<T extendsEnum<T>&Identifiable<S>, S extendsComparable<?super S>>List<T> getLower(T en){List<T> list =newArrayList<>();for(T t : en.getDeclaringClass().getEnumConstants()){if(t.getId().compareTo(en.getId())<0){
list.add(t);}}return list;}}
Da Enums Schnittstellen implementieren können, können sie zur strikten Durchsetzung des Singleton-Musters verwendet werden. Der Versuch, eine Standardklasse zu einem Singleton zu machen, ermöglicht ...
für die Möglichkeit, Reflexionstechniken zu verwenden, um private Methoden als öffentlich zu entlarven
für das Erben von Ihrem Singleton und das Überschreiben der Methoden Ihres Singletons mit etwas anderem
Aufzählungen als Singletons helfen, diese Sicherheitsprobleme zu vermeiden. Dies könnte einer der Gründe dafür gewesen sein, dass Enums als Klassen fungieren und Schnittstellen implementieren. Nur eine Vermutung.
for inheriting from your singleton and overriding your singleton's methods with something else. Sie können nur ein verwenden final class, um das zu verhindern
Dylanthepiguy
10
Dies ist für die Erweiterbarkeit erforderlich. Wenn jemand eine von Ihnen entwickelte API verwendet, sind die von Ihnen definierten Aufzählungen statisch. Sie können nicht hinzugefügt oder geändert werden. Wenn Sie jedoch eine Schnittstelle implementieren lassen, kann die Person, die die API verwendet, mithilfe derselben Schnittstelle eine eigene Aufzählung erstellen. Sie können diese Aufzählung dann bei einem Aufzählungsmanager registrieren, der die Aufzählungen zusammen mit der Standardschnittstelle zusammenfasst.
Edit: @Helper Method hat das perfekte Beispiel dafür. Stellen Sie sich vor, andere Bibliotheken definieren neue Operatoren und teilen dann einer Manager-Klasse mit, dass "Hey, diese Aufzählung existiert - registrieren Sie sie". Andernfalls können Sie Operatoren nur in Ihrem eigenen Code definieren - es gibt keine Erweiterbarkeit.
Aufzählungen sind nur verkleidete Klassen, also zum größten Teil alles, was Sie mit einer Klasse tun können, können Sie mit einer Aufzählung tun.
Ich kann mir keinen Grund vorstellen, warum eine Aufzählung keine Schnittstelle implementieren kann, und gleichzeitig kann ich mir auch keinen guten Grund dafür vorstellen.
Ich würde sagen, sobald Sie anfangen, Dinge wie Schnittstellen oder Methoden zu einer Aufzählung hinzuzufügen, sollten Sie wirklich darüber nachdenken, sie stattdessen zu einer Klasse zu machen. Natürlich bin ich mir sicher, dass es gültige Fälle für nicht-traditionelle Aufzählungssachen gibt, und da die Grenze künstlich wäre, bin ich dafür, die Leute dort tun zu lassen, was sie wollen.
"... also zum größten Teil alles, was man mit einer Klasse machen kann, kann man mit einer Aufzählung machen", aber ich kann nicht sagen, dass meine Aufzählung von einer abstrakten Klasse geerbt wird. Also ja, Betonung auf "größtenteils".
Adam Parkin
5
Dies liegt daran, dass Enums alle java.lang.Enum erweitern und Java-Klassen nur von einer Klasse aus erweitert werden können.
TofuBeer
6
Zum Beispiel, wenn Sie eine Logger-Aufzählung haben. Dann sollten Sie die Logger-Methoden wie Debug, Info, Warnung und Fehler in der Schnittstelle haben. Dadurch wird Ihr Code lose gekoppelt.
Am häufigsten wird dies verwendet, um die Werte von zwei Aufzählungen zu einer Gruppe zusammenzuführen und sie ähnlich zu behandeln. Sehen Sie sich beispielsweise an, wie Sie Obst und Gemüse verbinden .
Einer der besten Anwendungsfälle für mich, Enums mit Schnittstelle zu verwenden, sind Prädikatfilter. Dies ist eine sehr elegante Methode, um die mangelnde Typizität von Apache-Sammlungen zu beheben (falls andere Bibliotheken möglicherweise nicht verwendet werden).
Der obige Beitrag, in dem Strategien erwähnt wurden, hat nicht genug betont, was eine schöne, leichte Implementierung des Strategiemusters unter Verwendung von Aufzählungen bringt:
publicenumStrategy{
A {@Overridevoid execute(){System.out.print("Executing strategy A");}},
B {@Overridevoid execute(){System.out.print("Executing strategy B");}};abstractvoid execute();}
Sie können alle Ihre Strategien an einem Ort haben, ohne für jede eine separate Kompilierungseinheit zu benötigen. Sie erhalten einen schönen dynamischen Versand nur mit:
Strategy.valueOf("A").execute();
Lässt Java fast wie eine schöne, lose getippte Sprache lesen!
Aufzählungen sind wie Java-Klassen, sie können Konstruktoren, Methoden usw. haben. Das einzige, was Sie damit nicht tun können, ist new EnumName(). Die Instanzen sind in Ihrer Enum-Deklaration vordefiniert.
Was ist mit enum Foo extends SomeOtherClass? Also nicht ganz das Gleiche wie eine reguläre Klasse, in der Tat ganz anders.
Adam Parkin
@Adam: Ich würde sagen, dass die Art und Weise, wie Enums Klassen ähneln, viel zahlreicher ist als die Art und Weise, wie sie sich von Klassen unterscheiden. Aber nein, sie sind nicht identisch.
Scottb
Wenn Sie eine Aufzählung dekompilieren, sehen Sie, dass es sich um eine Klasse handelt, die die Aufzählung erweitert und deren "Konstanten" bereits in Konstruktor- / Initialisierungsfeldern instanziiert sind.
Cosmin Cosmin
3
Eine andere Möglichkeit:
publicenumConditionsToBeSatisfiedimplementsPredicate<Number>{
IS_NOT_NULL(Objects::nonNull,"Item is null"),
IS_NOT_AN_INTEGER(item -> item instanceofInteger,"Item is not an integer"),
IS_POSITIVE(item -> item instanceofInteger&&(Integer) item >0,"Item is negative");privatefinalPredicate<Number> predicate;privatefinalString notSatisfiedLogMessage;ConditionsToBeSatisfied(finalPredicate<Number> predicate,finalString notSatisfiedLogMessage){this.predicate = predicate;this.notSatisfiedLogMessage = notSatisfiedLogMessage;}@Overridepublicboolean test(finalNumber item){finalboolean isNotValid = predicate.negate().test(item);if(isNotValid){
log.warn("Invalid {}. Cause: {}", item, notSatisfiedLogMessage);}return predicate.test(item);}}
und mit:
Predicate<Number> p = IS_NOT_NULL.and(IS_NOT_AN_INTEGER).and(IS_POSITIVE);
Beim Erstellen von Konstanten in einer JAR-Datei ist es häufig hilfreich, Benutzer Enum-Werte erweitern zu lassen. Wir haben Enums für PropertyFile-Schlüssel verwendet und sind hängen geblieben, weil niemand neue hinzufügen konnte! Unten hätte viel besser funktioniert.
Ich habe eine JavaFX ComboBox mit den Werten einer Aufzählung gefüllt. Ich habe eine identifizierbare Schnittstelle (Angabe einer Methode: Identifizieren), mit der ich angeben kann, wie sich ein Objekt für Suchzwecke in meiner Anwendung identifiziert. Über diese Schnittstelle kann ich Listen aller Arten von Objekten (unabhängig davon, welches Feld das Objekt für die Identität verwendet) nach einer Identitätsübereinstimmung durchsuchen.
Ich möchte eine Übereinstimmung für einen Identitätswert in meiner ComboBox-Liste finden. Um diese Funktion in meiner ComboBox mit den Enum-Werten verwenden zu können, muss ich in der Lage sein, die identifizierbare Schnittstelle in meiner Enum zu implementieren (was im Fall einer Enum trivial zu implementieren ist).
Ich habe eine innere Aufzählung in einer Schnittstelle verwendet, die eine Strategie beschreibt, um die Instanzkontrolle (jede Strategie ist ein Singleton) von dort aus zu behalten.
publicinterfaceVectorizeStrategy{/**
* Keep instance control from here.
*
* Concrete classes constructors should be package private.
*/enumConcreteStrategyimplementsVectorizeStrategy{
DEFAULT (newVectorizeImpl());privatefinalVectorizeStrategy INSTANCE;ConcreteStrategy(VectorizeStrategy concreteStrategy){
INSTANCE = concreteStrategy;}@OverridepublicVectorImageGridIntersections processImage(MarvinImage img){return INSTANCE.processImage(img);}}/**
* Should perform edge Detection in order to have lines, that can be vectorized.
*
* @param img An Image suitable for edge detection.
*
* @return the VectorImageGridIntersections representing img's vectors
* intersections with the grids.
*/VectorImageGridIntersections processImage(MarvinImage img);}
Die Tatsache, dass die Aufzählung die Strategie implementiert, ist praktisch, damit die Aufzählungsklasse als Proxy für ihre eingeschlossene Instanz fungieren kann. das implementiert auch die Schnittstelle.
Es ist eine Art StrategieEnumProxy: P Der Clent-Code sieht folgendermaßen aus:
Antworten:
Aufzählungen müssen nicht nur passive Mengen (z. B. Farben) darstellen. Sie können komplexere Objekte mit Funktionalität darstellen und so sind Sie dann wahrscheinlich weitere Funktionalität zu diesem hinzufügen wollen - zB Sie Schnittstellen haben können wie
Printable
,Reportable
usw. und Komponenten , die diese unterstützen.quelle
Hier ist ein Beispiel (ein ähnliches / besseres findet sich in Effective Java 2nd Edition):
So erhalten Sie eine Liste der beiden einfachen + komplexen Operatoren:
Hier verwenden Sie also eine Schnittstelle, um erweiterbare Aufzählungen zu simulieren (was ohne die Verwendung einer Schnittstelle nicht möglich wäre).
quelle
Das
Comparable
Beispiel, das hier von mehreren Personen gegeben wurde, ist falsch, da diesEnum
bereits umgesetzt wird. Sie können es nicht einmal überschreiben.Ein besseres Beispiel ist eine Schnittstelle, die beispielsweise einen Datentyp definiert. Sie können eine Aufzählung zum Implementieren der einfachen Typen und normale Klassen zum Implementieren komplizierter Typen haben:
quelle
Es gibt einen Fall, den ich oft benutze. Ich habe eine
IdUtil
Klasse mit statischen Methoden, um mit Objekten zu arbeiten, die eine sehr einfacheIdentifiable
Schnittstelle implementieren:Wenn ich ein
Identifiable
enum
:Dann kann ich es
id
so bekommen:quelle
Da Enums Schnittstellen implementieren können, können sie zur strikten Durchsetzung des Singleton-Musters verwendet werden. Der Versuch, eine Standardklasse zu einem Singleton zu machen, ermöglicht ...
Aufzählungen als Singletons helfen, diese Sicherheitsprobleme zu vermeiden. Dies könnte einer der Gründe dafür gewesen sein, dass Enums als Klassen fungieren und Schnittstellen implementieren. Nur eine Vermutung.
Weitere Informationen finden Sie unter /programming/427902/java-enum-singleton und der Singleton-Klasse in Java .
quelle
for inheriting from your singleton and overriding your singleton's methods with something else
. Sie können nur ein verwendenfinal class
, um das zu verhindernDies ist für die Erweiterbarkeit erforderlich. Wenn jemand eine von Ihnen entwickelte API verwendet, sind die von Ihnen definierten Aufzählungen statisch. Sie können nicht hinzugefügt oder geändert werden. Wenn Sie jedoch eine Schnittstelle implementieren lassen, kann die Person, die die API verwendet, mithilfe derselben Schnittstelle eine eigene Aufzählung erstellen. Sie können diese Aufzählung dann bei einem Aufzählungsmanager registrieren, der die Aufzählungen zusammen mit der Standardschnittstelle zusammenfasst.
Edit: @Helper Method hat das perfekte Beispiel dafür. Stellen Sie sich vor, andere Bibliotheken definieren neue Operatoren und teilen dann einer Manager-Klasse mit, dass "Hey, diese Aufzählung existiert - registrieren Sie sie". Andernfalls können Sie Operatoren nur in Ihrem eigenen Code definieren - es gibt keine Erweiterbarkeit.
quelle
Aufzählungen sind nur verkleidete Klassen, also zum größten Teil alles, was Sie mit einer Klasse tun können, können Sie mit einer Aufzählung tun.
Ich kann mir keinen Grund vorstellen, warum eine Aufzählung keine Schnittstelle implementieren kann, und gleichzeitig kann ich mir auch keinen guten Grund dafür vorstellen.
Ich würde sagen, sobald Sie anfangen, Dinge wie Schnittstellen oder Methoden zu einer Aufzählung hinzuzufügen, sollten Sie wirklich darüber nachdenken, sie stattdessen zu einer Klasse zu machen. Natürlich bin ich mir sicher, dass es gültige Fälle für nicht-traditionelle Aufzählungssachen gibt, und da die Grenze künstlich wäre, bin ich dafür, die Leute dort tun zu lassen, was sie wollen.
quelle
Zum Beispiel, wenn Sie eine Logger-Aufzählung haben. Dann sollten Sie die Logger-Methoden wie Debug, Info, Warnung und Fehler in der Schnittstelle haben. Dadurch wird Ihr Code lose gekoppelt.
quelle
Am häufigsten wird dies verwendet, um die Werte von zwei Aufzählungen zu einer Gruppe zusammenzuführen und sie ähnlich zu behandeln. Sehen Sie sich beispielsweise an, wie Sie Obst und Gemüse verbinden .
quelle
Einer der besten Anwendungsfälle für mich, Enums mit Schnittstelle zu verwenden, sind Prädikatfilter. Dies ist eine sehr elegante Methode, um die mangelnde Typizität von Apache-Sammlungen zu beheben (falls andere Bibliotheken möglicherweise nicht verwendet werden).
quelle
Der obige Beitrag, in dem Strategien erwähnt wurden, hat nicht genug betont, was eine schöne, leichte Implementierung des Strategiemusters unter Verwendung von Aufzählungen bringt:
Sie können alle Ihre Strategien an einem Ort haben, ohne für jede eine separate Kompilierungseinheit zu benötigen. Sie erhalten einen schönen dynamischen Versand nur mit:
Lässt Java fast wie eine schöne, lose getippte Sprache lesen!
quelle
Aufzählungen sind wie Java-Klassen, sie können Konstruktoren, Methoden usw. haben. Das einzige, was Sie damit nicht tun können, ist
new EnumName()
. Die Instanzen sind in Ihrer Enum-Deklaration vordefiniert.quelle
enum Foo extends SomeOtherClass
? Also nicht ganz das Gleiche wie eine reguläre Klasse, in der Tat ganz anders.Eine andere Möglichkeit:
und mit:
quelle
Beim Erstellen von Konstanten in einer JAR-Datei ist es häufig hilfreich, Benutzer Enum-Werte erweitern zu lassen. Wir haben Enums für PropertyFile-Schlüssel verwendet und sind hängen geblieben, weil niemand neue hinzufügen konnte! Unten hätte viel besser funktioniert.
Gegeben:
und:
man könnte eine Aufzählung im Glas haben:
und ein Benutzer könnte es erweitern, um seine eigenen Farben hinzuzufügen:
quelle
Hier ist mein Grund warum ...
Ich habe eine JavaFX ComboBox mit den Werten einer Aufzählung gefüllt. Ich habe eine identifizierbare Schnittstelle (Angabe einer Methode: Identifizieren), mit der ich angeben kann, wie sich ein Objekt für Suchzwecke in meiner Anwendung identifiziert. Über diese Schnittstelle kann ich Listen aller Arten von Objekten (unabhängig davon, welches Feld das Objekt für die Identität verwendet) nach einer Identitätsübereinstimmung durchsuchen.
Ich möchte eine Übereinstimmung für einen Identitätswert in meiner ComboBox-Liste finden. Um diese Funktion in meiner ComboBox mit den Enum-Werten verwenden zu können, muss ich in der Lage sein, die identifizierbare Schnittstelle in meiner Enum zu implementieren (was im Fall einer Enum trivial zu implementieren ist).
quelle
Ich habe eine innere Aufzählung in einer Schnittstelle verwendet, die eine Strategie beschreibt, um die Instanzkontrolle (jede Strategie ist ein Singleton) von dort aus zu behalten.
Die Tatsache, dass die Aufzählung die Strategie implementiert, ist praktisch, damit die Aufzählungsklasse als Proxy für ihre eingeschlossene Instanz fungieren kann. das implementiert auch die Schnittstelle.
Es ist eine Art StrategieEnumProxy: P Der Clent-Code sieht folgendermaßen aus:
Wenn es die Schnittstelle nicht implementiert hätte, wäre es gewesen:
quelle