# Wann sollte man enum nutzen?



## Rudolf (4. Nov 2012)

Hi

es gibt ja viele Möglichkeiten enum zu nutzen, sei es für das Singleton-Pattern, sei es für das StatePattern usw.

Man kann enum immer dann nutzen, wenn man nicht mehr als eine Hierarche hat die aus mehreren basistypen besteht und einem gemeinsamen Obertypen. 

Aus einem anderen Thread meinte jemand bereits, dass man bei enum keine Instanzvariablen nutzen sollte, da die Konstanten public static sind und daraus Globale Variables resultieren. Gibt es weitere Kriterien an die man sich halten kann, sollte, bezüglich wann nutzt man enum und wann nicht?


----------



## Noctarius (5. Nov 2012)

Kein Enum als Instanzvariable? Wieso das nicht?

Ein Enum ist ein Aufzählungsdatentyp und als dieser sollte es auch genutzt werden, z.B. in unterem Beispiel "zu welchem Scope gehört ein Achievement?". Natürlich kann man das auch über int-Konstanten abbilden aber mit einem Enum bin ich auf der typensicheren Seite.


```
public enum AchievementScope
{
	Character,
	Account,
	Repository
}

public abstract class Achievement
{
	private final String id;
	private final AchievementScope scope;
	private final List<AchievementStage> stages;
	private final long target;

	...
}
```


----------



## bygones (5. Nov 2012)

Rudolf hat gesagt.:


> Aus einem anderen Thread meinte jemand bereits, dass man bei enum keine Instanzvariablen nutzen sollte, da die Konstanten public static sind und daraus Globale Variables resultieren.


meinst du dass die enum an sich keine instanzvariablen halten sollen oder dass eine Klasse kein enum als Instanzvariablen haben soll ?

zweites ist unsinn, natuerlich kann eine Klasse ein enum halten (siehe Noctarius bsp). Erstes ist dann fragwuerdig, wenn man sich das enum als Singleton ersatz baut. Wenn man den eigentlichen Sinn eines enums (aufzaehltyp mit festgelegter Menge), so spricht hier nichts dagegen.


----------



## Landei (5. Nov 2012)

Ich nutze Enums auch für rein statisch Utility-Klassen:


```
enum StringUtils {
   ;
   public static String makeList(String separator, String ... strings){...}
   ...
}
```


----------



## Noctarius (5. Nov 2012)

bygones hat gesagt.:


> ... wenn man sich das enum als Singleton ersatz baut.



Wobei laut Bloch ab Java 5 das Enum der "beste" Weg ist ein Type- und Serialization-Safe Singleton zu bauen


----------



## Rudolf (5. Nov 2012)

Noctarius hat gesagt.:


> Wobei laut Bloch ab Java 5 das Enum der "beste" Weg ist ein Type- und Serialization-Safe Singleton zu bauen



Danke, genau das hätte ich auch noch ergänzt. Seiner Meinung nach ist die beste aktuelle Umsetzung von Singletons über ein enum.

Und natürlich ist es Quatsch, dass Klassen keine enums als Felder haben sollen. Es ist umgekehrt gemeint. Enums sollten keine Felder haben, da sie im System nur einmal existieren, da sie public static sind.

Konkret geht es mir ums State-Pattern. Sollte man enum dafür nutzen? Meistens hat man sowas wie einen Datentyp State und verschiedene Implementierungen davon, die unterschiedliche Zustände abbilden. Und je nach Operation kann der Zustand des Objekts durch ein setzes einer neuen Stateimplementierung verändert werden. 

Ist sowas geläufig oder sollte man Implementierungen ala "state=new StateImp();" genutzt werden statt state=State.Imp über enums?


----------



## nillehammer (5. Nov 2012)

Für eine einfache Bestellabwicklung habe ich bereits enums als states benutzt. Aber, da gabs als States auch nur "eingegangen, bestätigt, abgeschlossen" ohne zusätzliche Funktion.


----------



## nillehammer (5. Nov 2012)

> Es ist umgekehrt gemeint. Enums sollten keine Felder haben, da sie im System nur einmal existieren, da sie public static sind.


Der Aussage möchte ich widersprechen. Enums können public, package-private und als innere "Klassen" sogar private sein. Ihre Instanz- und statischen Variablen können die gleichen Zugriffsmodifizierer haben, wie die in "normalen" Klassen. Felder machen auch bei enums durchaus Sinn. Dazu folgendes Beispiel:

```
public enum BefehleEnum {
  AUS(0),LAUTER(1), LEISER(2),AN(3);
 
  private final short befehlsCode;

  private BefehleEnum(int befehlsCode) {
    this.befehlsCode = (short) befehlsCode;
  }

  public short getBefehlsCode() {

   return this.befehlsCode;
  }
}
```


----------



## Noctarius (5. Nov 2012)

Allerdings sollten diese Instanzvariablen dann "Konstanten" sein. Veränderliche Werte sind tatsächlich schlecht an dieser Stelle.


----------



## nillehammer (5. Nov 2012)

Noctarius hat gesagt.:
			
		

> Allerdings sollten diese Instanzvariablen dann "Konstanten" sein. Veränderliche Werte sind tatsächlich schlecht an dieser Stelle.


Ja, i.d.R ist das so (deswegen auch das final in meinem Codebeispiel). Die Anwendungsfälle für variable Felder in enums sind dann doch recht begrenzt. Mir fällt jetzt jedenfalls gerade überhaupt keiner ein. Und ich habe auch noch nie variable Felder in enums verwendet.


----------



## bygones (5. Nov 2012)

Noctarius hat gesagt.:


> Wobei laut Bloch ab Java 5 das Enum der "beste" Weg ist ein Type- und Serialization-Safe Singleton zu bauen


*widerstehen* Singleton-Sinn-endloss-Diskussion....


----------



## Noctarius (5. Nov 2012)

nillehammer hat gesagt.:


> Ja, i.d.R ist das so (deswegen auch das final in meinem Codebeispiel). Die Anwendungsfälle für variable Felder in enums sind dann doch recht begrenzt. Mir fällt jetzt jedenfalls gerade überhaupt keiner ein. Und ich habe auch noch nie variable Felder in enums verwendet.



Mir würde auch keiner einfallen außer *hust* *hust* man nutzt ein Enum als Singleton *hust* *hust* --- Was? Wer hat das gesagt? 



bygones hat gesagt.:


> *widerstehen* Singleton-Sinn-endloss-Diskussion....



hrhr ich wusste ich fang sie damit an


----------



## KuhTee (5. Nov 2012)

Noctarius hat gesagt.:


> Wobei laut Bloch ab Java 5 das Enum der "beste" Weg ist ein Type- und Serialization-Safe Singleton zu bauen


Was auch einiges über die Sprache aussagt...


----------



## maki (5. Nov 2012)

KuhTee hat gesagt.:


> Was auch einiges über die Sprache aussagt...


Nicht wirklich über die Sprache, eher über die nicht verwendeten DI Frameworks im Projekt, mit letzterem braucht kein Mensch mehr ein GoF Singleton (und viele andere Dinge).
Blochs Buch war vor der Zeit als DI für Java spezifiziert wurde (JSR 330, JSR 299), muss man heute etwas differenzierter sehen.
Aber hier ging es ja gar nicht über Singletons oder DI Frameworks oder die Fehler der Java Sprache an sich...

Enums sind "feste" Aufzählungen, wenn man zur Laufzeit neue Objekte braucht, ist enum imho falsch.
Wenn man sich in der Situation wiederfindet, dass man gerne Vererben möchte (nicht nur Interfaces), nimmt man kein enum, sondern echte Klassen.
Enums dürfen Logik enthalten, ist einer der starken Seiten von Java Enums, da es sich nicht nur um Integer Konstanten handelt, sondern um echte Objekte, inkl. Typsicherheit etc.

Enums finde ich praktisch für ein paar Muster (Singleton ist wegen DI keines davon), Strategy oder State eben.


----------



## Noctarius (5. Nov 2012)

KuhTee hat gesagt.:


> Was auch einiges über die Sprache aussagt...



Ja das kein Mensch das Singleton braucht und eine Sprache deswegen keinen Support dafür benötigt


----------



## Gonzo17 (6. Nov 2012)

Landei hat gesagt.:


> Ich nutze Enums auch für rein statisch Utility-Klassen:
> 
> 
> ```
> ...



Öhm.. hilf mir bitte mal auf die Sprünge. Welchen Vorteil bietet in diesem Fall ein Enum gegenüber einer normalen Klasse?


----------



## Noctarius (6. Nov 2012)

Man spart sich den privaten Konstruktor ;-)


----------



## darekkay (6. Nov 2012)

Ist das wirklich eine empfehlenswerte Vorgehensweise? Ein "Aufzählungstyp", der keine Elemente enthält, dafür aber Hilfsmethoden - klingt nicht so Clean Code like, nur um sich

```
private Muh(){
}
```
zu sparen (was mit einer IDE automatisch erzeugt werden kann). Oder irre ich mich da?


----------



## tfa (6. Nov 2012)

> Ein "Aufzählungstyp", der keine Elemente enthält, dafür aber Hilfsmethoden - klingt nicht so Clean Code like


Das seh ich ähnlich. Wenn ich einen enum-Typ in der IDE sehe (als kleines, braunes (E)), habe ich die Erwartung, dass es sich auch um eine Enum handelt. Eine Utilty-Klasse würde da erstmal nur verwirren. Das ist so ähnlich, wie der Missbrauch von Interfaces zur Definition von Konstanten.


----------



## Landei (6. Nov 2012)

darekkay hat gesagt.:


> Ist das wirklich eine empfehlenswerte Vorgehensweise? Ein "Aufzählungstyp", der keine Elemente enthält, dafür aber Hilfsmethoden - klingt nicht so Clean Code like, nur um sich
> 
> ```
> private Muh(){
> ...



Aber genau das ist es: Eine Klasse ohne Instanzen. Es kann x verschiedene Gründe geben, warum ein Konstruktor privat ist, aber nur einen einzigen, eine Enum-Klasse ohne Instanzen zu schreiben: Man will keine.

Mengenlehre würde ohne die leere Menge auch nicht funktionieren...


----------



## bygones (6. Nov 2012)

Landei hat gesagt.:


> Aber genau das ist es: Eine Klasse ohne Instanzen. Es kann x verschiedene Gründe geben, warum ein Konstruktor privat ist, aber nur einen einzigen, eine Enum-Klasse ohne Instanzen zu schreiben: Man will keine.



halte ich fuer ein schwaches Argument und einen Missbrauch eines Sprachkonstrukts. Ein privater Konstruktor heisst natuerlich nicht sofort nach aussen, dass hiervon keine instanz gibt, aber warum soll man von aussen sehen koennen ob sie das hat oder nicht ?


----------



## tfa (6. Nov 2012)

> Es kann x verschiedene Gründe geben, warum ein Konstruktor privat ist, aber nur einen einzigen, eine Enum-Klasse ohne Instanzen zu schreiben: Man will keine.


Nach meiner bescheidenen Meinung würde ich es so sagen: Es kann x verschiedene Gründe geben, warum man eine [c]class[/c] schreibt, aber nur einen einzigen, ein [c]enum[/c] anzulegen: Man will einen Aufzählungstyp.


----------



## darekkay (6. Nov 2012)

Meine Frage war eigentlich, wie praxistauglich bzw. "clean" die Vorgehensweise ist. Als nichtsahnender Nutzer würde ich ein enum "Math" für eine Menge von Konstanten halten - und nur das. Ich erwarte dort zunächst keine statischen Hilfsmethoden. Klar, man kann es vielleicht im Header nachlesen (sofern dokumentiert) und/oder sich kurz ein paar Gedanken machen, warum ein enum so verwendet wird. Aber ich verlasse mich wie tfa eher auf das "braune E" in Eclipse und gehe davon aus, dass es genau das ist, wofür es ursprünglich gedacht war.


----------



## Landei (6. Nov 2012)

tfa hat gesagt.:


> Nach meiner bescheidenen Meinung würde ich es so sagen: Es kann x verschiedene Gründe geben, warum man eine [c]class[/c] schreibt, aber nur einen einzigen, ein [c]enum[/c] anzulegen: Man will einen Aufzählungstyp.



Sicher. Nur dass eine Aufzählung eben auch leer sein kann.

Aber ich denke, das ist eine Frage der Gewohnheit und Geschmacks. Ich bin eher der Typ, der sich fragt: Wenn man X erreichen will, kann man Y dazu verwenden? Andere mögen eher fragen, für welche Fälle  X ein bestimmtes Y gedacht ist, und es dann genau dafür einsetzen. Für beide Positionen lassen sich Argumente finden.


----------



## bygones (7. Nov 2012)

Landei hat gesagt.:


> Sicher. Nur dass eine Aufzählung eben auch leer sein kann.
> 
> Aber ich denke, das ist eine Frage der Gewohnheit und Geschmacks. Ich bin eher der Typ, der sich fragt: Wenn man X erreichen will, kann man Y dazu verwenden? Andere mögen eher fragen, für welche Fälle  X ein bestimmtes Y gedacht ist, und es dann genau dafür einsetzen. Für beide Positionen lassen sich Argumente finden.


"Achtung auf der A7 ist ein Geisterfahrer unterwegs"
"Wie einer ? Hunderte...."


----------



## Tomate_Salat (7. Nov 2012)

bygones hat gesagt.:


> "Achtung auf der A7 ist ein Geisterfahrer unterwegs"
> "Wie einer ? Hunderte...."



Der ist gut , aber passender wäre imho:
"Achtung Tracktor mit Maischewage auf der A7..."


----------



## Landei (7. Nov 2012)

bygones hat gesagt.:


> "Achtung auf der A7 ist ein Geisterfahrer unterwegs"
> "Wie einer ? Hunderte...."



Wenn alle so dächten, würden wir immer noch Nullen und Einsen auf Tontafeln ritzen...


----------

