Enum oder normale Klasse?

Peppton66

Mitglied
Hallo Forengemeinde,
Ich schreibe als Hobbyprojekt einen Lebensmitteltracker und hab dafür einen Datensatz von etwa 1k Lebensmitteln von welchen ich neben den Namen und Maßeinheit etwa 10 verschiedene Mikronährstoffe der Lebensmittel erfassen möchte.

Als Namen der Lebensmittel verwende ich einen String, als Maßeinheit ein Enum mit Tasse, Löffel usw. als konstanten:

Code:
public class Food{

private String name;

private FoodUnit foodUnit;
...
}

Bzgl der Abbildung der Mikronährstoffe bin ich mir allerdings nicht sicher, wie ich weiter vorgehen soll.
Die Mikronährstoffe haben einen Namen (z.B. Salz), ein Kürzel (z.B. NaCi) und eine Eineit (z.B. "g" oder "mg"). Die Maßeinheiten für die Mikronährstoffe finden sich ebenfalls in einem Enum.
Im konkreten Fall kommt zusätzlich die Menge hinzu. Also eine Tasse Suppe 0.15g Salz.

Wie würdet ihr das umsetzen?
Meine Ideen (wovon ich nicht weiß, welche die sinnvollste wäre):

1.
Ein Enum, welches die Mikronährstoffe mitsamt der drei Attribute abbildet.
+ Eine Klasse mit dem Enum + der Menge als double als Attribute

2.
Eine einfache Klasse mit Namen, Kürzel, Einheit und Menge als Attribute. (evtl. mit Vererbung, "Micronutrient" als abstrakte klasse und die einzelnen Nährstoffe als Unterklassen wobei es sich eher um Entitäten ohne Logik handelt)

3.
Für jeden Mikronährstoff eine eigene Klasse mit dem Namen als Klassenname und Kürzel + Maßeinheit + Menge als Attribut.


Und wie würdet ihr die Mirkonährstoffe in die Klasse fürs Lebensmittel schreiben?
Einzeln, oder gebündelt als Array oder Collections?
Ich hoffe, mein Problem ist für euch nachvollziehbar dargestellt.

Vielen Dank im Voraus
 

Robert Zenz

Top Contributor
Die Frage zwischen Enum und Klasse ist die: Ist die Menge endlich und in wenigen Zeilen im Code abbildbar?

Was kann man zum Beispiel als Enum abbilden?

* Einheiten (Gramm, Meter, Zeit, ...)
* SI-Praefixe (Kilo, Milli, Zeta, ...)
* Eigenschaften welche bekannt/limitiert sind (Farben, Groeszen, Typen, ...)

Letzteres ist aber schon ein grauer Bereich, der Kanckpunkt ist "bekannt und limitert". Was sollte man dann als Klassen abbilden?

* Eigenschaften welche bei der Entwicklung nicht bekannt sind (Farben, Groeszen, Typen, ...)
* Eigenschaften welche zwar bekannt sind, aber eine grosze Anzahl haben (Farben, ...)
* Alles was Daten getrieben ist

Um deine Frage etwas direkter zu beantworten, ich wuerde die Mengeneinheit als Enum machen (sehen wir's ein, Gramm+Praefix sind ein sehr gut definierter Satz an Dingen, zusaetzlich willst du vermutlich nicht "spontane" Benutzereinheiten wie Tassen, Prisen oder "Aequivalent zu drei Meisenbeinen" unterstuetzen). Die Zutat selbst wuerde ich als datengetriebene Klasse sehen, also die sollte zur Laufzeit entstehen, denn sonst muesstest du jedes bekannte Lebensmittel und jede bekannte Zutat in deinem Code abbilden, und das kann schon bei Salz oder Reis sehr schwierig werden.

Also sowas wie:

Java:
public class Zutat {
    public String getName();
    public Mengeneinheit getMengeneinheit();
    public int getMenge(); // Oder float, oder double, oder BigDecimal. Kommt darauf an welche Genauigkeit du willst und brauchst.
}

public enum Mengeneinheit {
    MG, G, DAG, KG;
}

Damit kannst du dir dann zur Laufzeit die Zutaten von irgendwo ziehen, zum Beispiel aus einer Datenbank oder auch nur aus einer einfachen Datei. Wenn dann eine hinzukommt, musst du diese nur in deiner Datenquelle hinzufuegen und nicht dein ganzes Programm nochmal neu kompilieren.
 

Peppton66

Mitglied
Vielen Dank für deine Antwort @Robert Zenz
Das grundsätzliche Prinzip von Enums und die Verwendung ist mir bekannt.

Bei den Mikronährstoffen selbst handelt es sich ja ebenfalls um eine endliche und in wenigen Zeilen darstellbare Menge.
Ich glaube du hast in meinem Fall eine Ebene übersehen oder ich habs nicht wirklich deutlich gemacht.

Also Mikronährstoffe: Fest definitiert (10 Stück) (Jeweils 3 Feste Eigenschaften -> Bsp. "Salt", NacI, G)
Und Lebensmittel: Sollen (bzw. werden) zur Laufzeit aus einer Datei als Datenquelle generiert. (Eigenenschaften sind neben Namen des Lebensmittels auch immer die 10 Mikronährstoffe + Mengenangaen dieser)

Folgende Konstellation an Enums würden mir deshalb ebenfalls logisch erscheinen (insb. in Bezug auf dein letztes Beispiel der Aufzählung):
Java:
public enum Unit {
    G, MG,UG;
}
Java:
public enum Micronutrient {
    NACI("Salt", Unit.G),
    B1("Thiam", Unit.MG),
    Zn("Zinc", Unit.MG);
    public final String label;
    public final Unit unit;

    private Micronutrient(String label, Unit unit){
        this.label=label;
        this.unit=unit;
    }
}

Würdest du die Verbindung (Also Mirkonährstoffs-Enum + Konkrete Menge) mit einer extra Klasse Lösen und dann als Attribut in die Klasse fürs Lebensmittel schreiben?
Java:
public class DoseOfAMicronutrient {
    private Micronutrient micronutrient;
    private double quantity;

    public DoseOfAMicronutrient(Micronutrient micronutrient, double quantity) {
        this.micronutrient = micronutrient;
        this.quantity = quantity;
    }
}

Java:
public class Food {
    private String name;
    private DoseOfAMicronutrient salt;
    private DoseOfAMicronutrient zinc;

    public Food(String name, double saltAmount, double zincAmount){
        this.name=name;
        this.salt=new DoseOfAMicronutrient(Micronutrient.NACI, saltAmount);
        this.zinc=new DoseOfAMicronutrient(Micronutrient.Zn, zincAmount);
    }
}
 

Robert Zenz

Top Contributor
Also Mikronährstoffe: Fest definitiert (10 Stück) (Jeweils 3 Feste Eigenschaften -> Bsp. "Salt", NacI, G)
Dann koennen das Enums werden, sind ja eine fix-definierte Menge welche sich nicht aendern (sollte).

Würdest du die Verbindung (Also Mirkonährstoffs-Enum + Konkrete Menge) mit einer extra Klasse Lösen und dann als Attribut in die Klasse fürs Lebensmittel schreiben?
Ja. Allerdings wuerde ich eine Liste verwenden in Food damit man nicht die 10 Felder anlegen muss. Dann muss man aber etwas darauf achten dass die nicht doppelt sein koennen.
 

White_Fox

Top Contributor
Du könntest auch einfach eine generische Klasse Micronutrient schreiben. Für jeden Mikronährstoff, den du erfassen willst, baust du dann ein Objekt daraus und gibst ihm den Namen und andere Eigenschaften über eine Datei mit.

Das hätte u.a. den Vorteil, daß du ohne weiteres neue Nährstoffe zur Laufzeit aufnehmen könntest, sollte doch mal ein Lebensmittel auftauchen daß noch irgendwas Seltenes mit dabei hat. Auch sonst ließe sich die Liste einfacher erweitern, und du läufst weniger in die Falle, für einen Mikronährstoff Sonderlocken zu drehen (if(nutrient == MicroNutrient.SALT){...}). Wenn noch mehr Nährstoffe dazukommen könnten, dann kann es auch passieren, das man später feststellt daß man bestimmte Nährstoffe doch nicht mehr auflisten will.

So, wie du Mikronährstoffe beschreibst, würde ich aus dem Bauch heraus eher sagen, daß die zu den Daten gehören, Enums würde ich da eher nicht benutzen. Enums sind gut für z.B. die Farben oder Koordinaten bei einem Schachspiel, Richtungsangaben wie Links/Rechts, oder Himmelsrichtungen auf einem Kompass.
Abzählbare Einheiten, deren Anzahl aber eine konzeptuelle Begrenzung hat. Daß du mit zehn Mikronährstoffen arbeiten willst ist zwar eine Begrenzung, die aber allein deiner Willkür unterliegt und die sich folglich ändern kann.

Wobei ich dazu aber sagen muß, daß der Robert garantiert weitaus mehr Quelltext geschrieben hat als ich. (So ziemlich jeder hier, der was Kluges schreibt, hat sicher mehr Quelltext geschrieben als ich das je tun werde.)
 

Barista

Top Contributor
Ja. Allerdings wuerde ich eine Liste verwenden in Food damit man nicht die 10 Felder anlegen muss. Dann muss man aber etwas darauf achten dass die nicht doppelt sein koennen.
Hierfür würde sich nach meiner Meinung eine Map eigenen, Key wäre die Art des Micronährstoffes (wahrscheinlich ein Enum) und Value die Menge mit Maßeinheit.

Falls man die Maßeinheit für den jeweiligen Micronährstoff festlegt, kann der Value auch einfach ein Double sein (oder Float).

Beim Übergang vom Value zur Welt außerhalb der Map könnte man Double und Maßeinheit verbinden.

Dazu sollte man die Map in einer Klasse kapseln.

Interessant in diesem Zusammenhang ist auch, dass es mal eine Lösung im JDK für physikalische Einheiten geben sollte

Suche mal nach "java physikalische einheiten".

Ich habe dieses gefunden:

JavaPro - JSR-385 hätte Mars Orbiter retten können

Georg-August-Universität Göttingen - Erweiterung der Sprache Java um ein Konzept zum Mitführen von Maßeinheiten
 

Peppton66

Mitglied
Danke @White_Fox
An eine Generische Klasse hatte ich gar nicht gedacht, deinen Gedanken kann ich aber auch nicht ganz folgen.

Wird MicroNutrient generisch, mit welchen Typen würde ich die Objekte dann später erstellen?
Also für jeden Mikronährstoff eine eigene Klasse?

MicroNutrient<Salt> SaltDosage = new Micronutrient<Salt>(0.2, UNIT.G) ?
In dem Fall hätte ich anstatt einer Enum sehr viele Klassen, welche sich bis auf den Namen nicht unterscheiden.



Danke @Barista. Ich hab mich jetzt für folgende (ich denke saubere Lösung) entschieden.
Ein Enum, welches die Mikronährstoffe repräsentiert:

Java:
public enum Micronutrient {
    VITAMIN_A_RE("RE", Unit.UG),
    VITAMIN_A_RAE("RAE", Unit.UG),
    RETINOL("Retinol", Unit.UG);

    public final String shortening;
    public final Unit unit;

    private Micronutrient(String shortening, Unit unit){
        this.shortening=shortening;
        this.unit=unit;
    }

Und eine Map in meiner Klasse Food. Eine Methode nimmt die genauen Werte für das Lebensmittel in einer Liste entgegen und Iteriert zum füllen der Map mit den Werten über das Enum.
Nicht 100% optional, weil ich nicht vorhandene Werte mit 0 oder negativen Zahlen abbilden müsste aber für den Zweck reichts und die Klasse Food kann unangetastet bleiben, wenn neue Mikronährstoffe hinzukommen.


Java:
    private Map<Micronutrient, Double> micronutrients;

    public boolean setMironutrientDosages(ArrayList<Double> micronutrientValues){
        micronutrients.clear();
        if(micronutrients.size()!=micronutrientValues.size())
            return false;
        
        for(int i=0; i<Micronutrient.values().length; i++)
            micronutrients.put(Micronutrient.values()[i], micronutrientValues.get(i));
        return true;
    }
 

White_Fox

Top Contributor
Danke @White_Fox
An eine Generische Klasse hatte ich gar nicht gedacht, deinen Gedanken kann ich aber auch nicht ganz folgen.

Wird MicroNutrient generisch, mit welchen Typen würde ich die Objekte dann später erstellen?
Also für jeden Mikronährstoff eine eigene Klasse?
Nein, ich meine eine völlig generische Klasse MicroNutrient. Die jedes beliebige MicroNutrient sein kann:

Java:
public class MicroNutrient{
    private String name;
    
    public MicroNutrient(String name){
        this.name = name;
    }
    
    public String name(){
        return name;
    }
}

Dazu noch eine statische Klasse Nutrients. Diese Klasse liest alle Nutrients aus einer Datei ein. XML, CSV, was dir beliebt. Und erstellt und verteilt die MicroNutrient-Obekte.

Java:
public static class MicroNutrients{
    private ArrayList<MicroNutrient> micronutrients;
    
    public static void loadNutrients(){
        micronutrients = new ArrayList<>();
        //...lade Mikronährstoffe...
    }
    
    public List<MicroNutrient> listMicroNutrients(){
        return micronutrients.clone();
    }
}
 

White_Fox

Top Contributor
Um das mal allgemeiner auszuführen:
Die Klasse "MicroNutrient" ist eine Klasse, die keine Methoden besitzt mit der ihre Daten verändert werden können. Also nix wie setName(String name) oder dergleichen. Alle Daten, die diese Klasse hat, werden im Konstruktor angeliefert.

Wenn du es richtig kugelsicher haben willst, machst du ein eigenes Paket dafür auf, und machst den Konstruktor von MicroNutrient package private (also keinen Sichtbarkeitsmodifizierer vorne dranschreiben). Nur die Klasse selbst und deren Zugriffsmethoden (wie z.B. public String name();) sind public.
Das verhindert, daß du dir die Daten irgendwie kaputtschreiben kannst.

Bedenke dabei, daß z.B. die Menge von irgendetwas keine Eigenschaft des Stoffes sind. 20g Salz sind keine Eigenschaft vom Salz, sondern z.B. der Portion Pommes, auf der das Salz liegt.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
volcanos enum und switch (neu): falschen Wert mit IllegalArgumentException oder mit EnumConstantNotPresentException abfangen ? Java Basics - Anfänger-Themen 51
X Enum Abfrage ohne if, for, while oder switch Java Basics - Anfänger-Themen 21
U Warum kann ich die Methode in der ENUM Klasse nicht aufrufen? Und warum geht die Switch nicht? Java Basics - Anfänger-Themen 8
D Frage bzgl. Enum-Handhabung Java Basics - Anfänger-Themen 16
S Java Enum Java Basics - Anfänger-Themen 2
I Validation, ob String ein Wert aus einem Enum enthält Java Basics - Anfänger-Themen 3
V Enum Java Basics - Anfänger-Themen 1
C Farben als Enum Java Basics - Anfänger-Themen 3
N enum Attribut von Objekten einer Hashmap ausgeben Java Basics - Anfänger-Themen 6
I JAXB und Enum Java Basics - Anfänger-Themen 7
M Enum-Variable HashMap zuweisen Java Basics - Anfänger-Themen 5
B Enum innerhalb einer Klasse / anderes Konzept Java Basics - Anfänger-Themen 8
N Enum Typen, was passiert intern mit ihnen? Java Basics - Anfänger-Themen 2
A enum Java Basics - Anfänger-Themen 6
O Enum Array Rekursiv abarbeiten Java Basics - Anfänger-Themen 44
B ENUM to List<String> konvertieren Java Basics - Anfänger-Themen 2
N Java Enum converter Methode Java Basics - Anfänger-Themen 5
F Enum von Ländern Java Basics - Anfänger-Themen 8
J Klassen Enum als Informationsträger Java Basics - Anfänger-Themen 10
T Datentypen enum static Chaos (blutiger anfänger) Java Basics - Anfänger-Themen 5
R Enum ist das gleiche wie? Java Basics - Anfänger-Themen 15
P Klassen Richtige Anwendung einer Enum-Klasse Java Basics - Anfänger-Themen 11
E Datentypen Problem beim Speichern von enum. Java Basics - Anfänger-Themen 10
J Compiler-Fehler class interface or enum expected Java Basics - Anfänger-Themen 1
E Objektvergleich Enum Java Basics - Anfänger-Themen 7
kilopack15 Euromünzen in enum als Liste ausgeben Java Basics - Anfänger-Themen 11
N Enum als generischer Typ Java Basics - Anfänger-Themen 4
H Datentypen Fehler bei Verwendung von enum Java Basics - Anfänger-Themen 9
lBlKha0s Fehlermeldung : class interface or enum expected Java Basics - Anfänger-Themen 9
T error: class, interface, or enum expected Java Basics - Anfänger-Themen 5
S Menüauswahl per Enum Java Basics - Anfänger-Themen 12
F Enum via String definieren Java Basics - Anfänger-Themen 2
L Compiler-Fehler error: class, interface or enum expected Java Basics - Anfänger-Themen 2
M java.lang.Enum.valueOf(Unknown Source) Java Basics - Anfänger-Themen 2
M Enum-Variabel-Abfrage funktioniert nicht? Java Basics - Anfänger-Themen 2
P Fallunterscheidung mit Überprüfung (enum) Java Basics - Anfänger-Themen 11
H enum Type Java Basics - Anfänger-Themen 6
F Operatoren Enum aus Textdabei laden Java Basics - Anfänger-Themen 3
P enum: cannot be resolved to a type Java Basics - Anfänger-Themen 2
kaoZ Variablen Konstantensammlung vs. Enum Java Basics - Anfänger-Themen 9
H Enum außerhalb einer Klasse? Java Basics - Anfänger-Themen 2
K OOP Aufzählungstypen! enum Currency!!! Java Basics - Anfänger-Themen 5
F ENUM als Variable Java Basics - Anfänger-Themen 4
M Enum: Zugriff auf Konstanten Java Basics - Anfänger-Themen 7
W Enum Konstruktor Type Java Basics - Anfänger-Themen 2
A Erste Schritte ENUM - Werte zurückgeben Java Basics - Anfänger-Themen 5
D Enum als Parameter Java Basics - Anfänger-Themen 6
B Variablen Instanz von Enum zur Laufzeit erstellen und zuweisen Java Basics - Anfänger-Themen 2
B Datentypen Enum vererben/gruppieren? Java Basics - Anfänger-Themen 6
F Datentypen enum Java Basics - Anfänger-Themen 5
J Enum zählen Java Basics - Anfänger-Themen 8
D Einlesen eines Enum-Wertes per console Java Basics - Anfänger-Themen 3
K String mit ENUM vergleichen? Java Basics - Anfänger-Themen 6
N enum vergleiche Klammern? Java Basics - Anfänger-Themen 5
J public enum? in Java Java Basics - Anfänger-Themen 9
D Erste Schritte Enum - das unbekannte Wesen Java Basics - Anfänger-Themen 3
Y ENUM auslesen (Name des ENUM als Variable) Java Basics - Anfänger-Themen 4
P Compiler-Fehler "class, interface, or enum expected" Java Basics - Anfänger-Themen 5
K class, interface or enum expected Java Basics - Anfänger-Themen 14
pg1337 enum-Aufgabe Java Basics - Anfänger-Themen 5
N was sagt enum aus? Java Basics - Anfänger-Themen 3
S Methoden Enum Parameter in Methode Java Basics - Anfänger-Themen 7
G Datentypen enum Frage Java Basics - Anfänger-Themen 3
R Probleme mit Enum Java Basics - Anfänger-Themen 10
B Enum: Instanzen Java Basics - Anfänger-Themen 10
B Generic? Enum - So lösbar? Java Basics - Anfänger-Themen 8
T class, interface, or enum expected Java Basics - Anfänger-Themen 2
M Vererbung Enum Vererbung/Polymorphie Java Basics - Anfänger-Themen 2
P Enum Attribut in Konstruktoren Java Basics - Anfänger-Themen 10
4 Enum Problem Java Basics - Anfänger-Themen 2
turmaline Bindestrich in enum? Java Basics - Anfänger-Themen 5
T Enum - Key als Value ermitteln Java Basics - Anfänger-Themen 7
X enum Fehlermeldung "The public type Day must be defined in its own file" Java Basics - Anfänger-Themen 8
T ist enum.ordinal keine Konstante? Java Basics - Anfänger-Themen 7
R State machine mit enum Java Basics - Anfänger-Themen 9
L enum aus Integer umwandeln Java Basics - Anfänger-Themen 3
C Klasseninstanzierung mit enum-Parameter erzwingen Java Basics - Anfänger-Themen 2
I Enum in String Java Basics - Anfänger-Themen 4
N enum richtig verwenden Java Basics - Anfänger-Themen 5
M for(Enum..., ButtonGroup.getElements()... Java Basics - Anfänger-Themen 3
StrikeTom Fragen zu enum Java Basics - Anfänger-Themen 4
A Was ist performanter für Konstanten, enum oder static variablen Java Basics - Anfänger-Themen 5
L String zu Enum parsen Java Basics - Anfänger-Themen 8
J Datentypen Array in enum, ?? Wozu ?? Java Basics - Anfänger-Themen 3
S OOP Durch ein Enum iterieren... Java Basics - Anfänger-Themen 47
K Datentypen enum und liste Java Basics - Anfänger-Themen 7
S String - Enum Java Basics - Anfänger-Themen 3
H Eine enum switchen? Java Basics - Anfänger-Themen 7
G enum für Typsicherheit Java Basics - Anfänger-Themen 9
J class, interface, or enum expected - finde Fehler nicht. Java Basics - Anfänger-Themen 4
J OOP enum Java Basics - Anfänger-Themen 2
O Problem (Enum) Java Basics - Anfänger-Themen 14
S Enum als Index Java Basics - Anfänger-Themen 5
H Enum --> int ?? Java Basics - Anfänger-Themen 3
tanja enum in java Java Basics - Anfänger-Themen 3
D class, interface or enum expected Java Basics - Anfänger-Themen 2
A OOP Übergabe eines Wertes an den enum Konstruktor Java Basics - Anfänger-Themen 12
T Simple Enum Fragen Java Basics - Anfänger-Themen 6
J class, interface, or enum expected Java Basics - Anfänger-Themen 4
R Enum und dann setter Setzen? Java Basics - Anfänger-Themen 44

Ähnliche Java Themen

Neue Themen


Oben