Frage bzgl. Enum-Handhabung

Detlef7able

Aktives Mitglied
Guten Tag,

ich bearbeite gerade eine Übungsaufgabe wo eine Person erstellt werden soll, die Person setzt sich aus den Klassen Name und Adresse zusammen.

Eine Person soll Vorname, Name, Adresse, Geburtsdatum und Geschlecht besitzen. Beim Geschlecht soll enum verwendet werden. Bin mir da sehr unsicher, wie man da am besten vorgehen sollte. Ob das mit dem Datum so hinhaut weiß ich auch nicht.

Java:
import java.time.LocalDate;
import java.util.Calendar;
import java.util.Date;


public class Person {
      private Name name;
      private Address address;
      private LocalDate date;
      private static Geschlecht gesch;
      
      public enum Geschlecht {male, female , diverse}

      
      /** Construct a person with default properties */
      public Person() {
        this(new Name("Max",'a',"Mustermann"),
          new Address("Musterstr", 35, "99999", "Stadt"),
          LocalDate.now(),
          gesch=Geschlecht.diverse);
      }
    
    
      /** Construct a person with specified name and address */
      public Person(Name name, Address address, LocalDate date, Geschlecht gesch) {
        this.name = name;
        this.address = address;
        this.date=date;
        this.gesch=gesch;
        
      }

      /** Return name */
      public Name getName() {
        return name;
      }

      /** Set a new name */
      public void setName(Name name) {
        this.name = name;
      }

      /** Return address */
      public Address getAddress() {
        return address;
      }

      /** Set a new address */
      public void setAddress(Address address) {
        this.address = address;
      }
      
      public LocalDate getDate() {
            return date;
        }


        public void setDate(LocalDate date) {
            this.date = date;
        }


        public static Geschlecht getGesch() {
            return gesch;
        }


        public static Geschlecht setGesch(Geschlecht gesch) {
            Person.gesch = gesch;
            return gesch;
        }

      /** Override the toString method */
      @Override
      public String toString() {

        return '\n' + name.getFullName() + '\n' +
          address.getFullAddress() + '\n';
      }
      
    }

In Zeile 29 wird mir angezeigt: "The static field Person.gesch should be accessed in a static way". Was bedeutet das?

Vielen Dank im Voraus!
 
Die Variable gesch (Wieso kürzt cdu sowas ab?) ist static. Und Du greifst nicht über die Klasse darauf zu.

Daher wäre die Frage: Wieso ist die Variable static? Was bezweckst Du damit?

Und noch ein Hinweis: Konstanten und Enum Elemente werden in Screaming Case geschrieben, also komplett in Grossbuchstaben.
 
Die Sache mit dem enum hab ich irgendwo abgeschrieben ohne mir was dabei zu denken. Oder ich hatte es ohne static hingeschrieben und dann irgendwelche Fehlermeldungen erhalten, daraufhin dann die Quickfixes benutzt und static integriert.

Wie müsste es denn sein ohne static?
 
Dann schau doch einfach mal, was das Schlüsselwort static macht. Wenn du es verstanden hast, dann wirst du schauen können, ob du es brauchst oder nicht.

Ich halte es für sehr wichtig, dass hier ein gewisses Verständnis kommt, denn das ist existenziell. Auch die Frage
Wie müsste es denn sein ohne static?
beantwortet sich dann von ganz alleine denke ich mal.
 
Ja ich würde es gern als nicht statisch deklarieren.

Wie kann ich das enum im default-Konstuktor dann auf einen bestimmten Wert setzen? Bekomme das nicht auf die Reihe.

3 Geschlechter reichen mir zunächst.
 
Woran scheitert es denn dann? Hast denn die nicht statische Variable deklarieren können? Wie versuchst Du, da einen Wert zu setzen? Welche Fehlermeldung bekommst Du?
 
Ich weiß es grundsätzlich nicht, habe vorher nie enum verwendet.
Muss ich hier eine Variable erzeugen und zuweisen oder verhält es sich wie ein Klassenaufruf?
 
Die Verwendung von "enum" macht Sinn, wenn man (viele (und sich schnell zu erweiternde)) switch/case oder if/else-Codes vermeiden will. "static" wird als 'konstante Variable' genutzt (und teilweise missbraucht. Zudem ist es kontra-intuitiv, diese in einer Klasse zu definieren, obwohl eine solche Variable (oder Funktion) mit der Klasse sonst nichts zu tun hat).
 
also um mal ein Beispiel zu nennen ich habe ein enum mit 4 werten und das kann sonst gar nichts dann hab ich dieses switch case dazu

Java:
                switch (newPhase)
                {
                    case DRAW_PHASE -> drawPhaseSequence();
                    case MAIN_PHASE -> mainPhaseSequence();
                    case BATTLE_PHASE -> battlePhaseSequence();
                    case END_PHASE -> endPhaseSequence();
                }

das enum macht es halt übersichtlicher im ganzen, als wie wenn man konstrukte aus booleans zusammen baut

zb ein online und offline status von einem computer kann mit true oder false implementiert werden
aber man kann es auhc mit ienem enum implementieren das ONLINE und OFFLINE als Werte hat, da ist es dann halt beim enum eindeutiger zu lesen...du kannst aber auch ein enum in eine entsprechende java klasse umwandeln... wird in den meisten tutorials sogar 1 mal vorgeführt wenns um enums geht
 
Beispiel
Java:
enum Foo {
    EINS,
    ZWEI,
    DREI
}

class Bar {
    
    Foo foo;
    
    Bar(Foo foo) {
        this.foo = foo;
    }
}

// Aufruf z. B.

Bar bar = new Bar(Foo.ZWEI);
 
Ich weiß es grundsätzlich nicht, habe vorher nie enum verwendet.
Generell ist ein Enum einfach nur ein Typ wie jeder Andere auch. Die Variablendeklaration ist daher unabhängig davon, was für ein Typ da verwendet wird.

Du hats ja auch schon eine gültige Variablendeklaration gehabt:
private static Geschlecht gesch;
Du hast also erst ein "private", ein Modifizierer, der die Sichtbarkeit der Variable setzt. Alternativen hier sind noch public und protected. Wenn nichts angegeben ist, dann ist es "package private".

Dann kommt das "static", das die Variable statisch macht, d.h. die Variable wird zu einer Klassenvariable. Die Alternative ist, dies einfach weg zu lassen. Dann wäre die Variable eine Instanzvariable und wäre somit ein Teil der Instanz. (Das erklärt dann auch etwas meine Ratlosigkeit bei deiner Frage bezüglich "Wie sieht es ohne static aus?" -> Halt ohne static. Es bleibt alles sonst.

Dann kommt der Typ. Das kann also eine andere Klasse sein (Bei Dir hast Du Name. Address, ...) oder ein primitiver Datentyp (int, double, boolean, ...) ... Wenn es sich um ein Array handelt, dann sind auch noch "[]" dahinter.

Und am Ende der Deklaration kommt dann der Bezeichner der Variable.

Das wäre die Variablendeklaration in Kürze zusammengefasst. Das static müsste also einfach gestrichen werden:
private Geschlecht gesch;

Dann noch ein kurzer Absatz zu:
In Zeile 29 wird mir angezeigt: "The static field Person.gesch should be accessed in a static way". Was bedeutet das?
Statische Elemente sollten auch im Code erkennbar sein, d.h. es wird über die Klasse auf diese zugegriffen. So ist erkennbar, dass es eine statische Variable ist und man kann gar nicht vermuten, dass es eine Instanzvariable ist. Diese Warnung, die Du da gesehen hast, ist also nur ein dezenter Hinweis gewesen, dass Da vermutlich etwas falsch ist.

Und dann auch noch einmal der kurze Blick: Was ist ein Enum?
Unter dem Strich ist Enum auch nur eine (spezielle) Klasse. Diese ist lediglich etwas eingeschränkt: Es kann zur Laufzeit keine weitere Instanz erzeugt werden. Das ist aber auch schon eigentlich alles. Du kannst in einem Enum also extrem viel machen: Konstruktor mit Parametern, Methoden, Instanzvariablen, ...

Wenn Du das gelesen hast, wirst Du evtl. ins Stocken geraten sein: Zur Laufzeit kann keine neue Instanz erstellt werden aber man hat Konstruktoren? Wie passt das denn? Dazu klaue ich mir das Beispiel von @temi und fügre da einen Konstruktor mit einem Parameter ein:

Java:
enum Foo {
    EINS(1),
    ZWEI(2),
    DREI(3);
    
    private int value;
    
    public int getValue() { return value; }
    
    Foo(int value) {
        this.value = value;
    }
}

Hier wird dann deutlich: Die Auflistung der Enumwerte ist schon eine Art Konstruktoraufruf. Wenn noch mehr Inhalte kommen sollen, dann muss nach dem letzten Wert ein ";" kommen. In dem Beispiel habe ich jetzt einfach noch ein Instanzvariable value, einen Getter dazu und eben den Konstruktor.

Das musst Du aber im Detail vermutlich nicht einmal wissen. Mir ist nur das Verständnis ganz am Anfang wichtig: Es ist wie eine Klasse. Daher sieht die Nutzung ebenso aus. Also egal, ob du eine Variable deklarierst oder ein Parameter: Du kannst es einfach so nutzen wie Du eben auch die Klassen verwendest.
 
Ich bedanke mich für die ausführlichen Antworten.

Habe noch ein weiteres Anliegen.

Ich habe eine Klasse Person und diese Klasse Person setzt sich aus den Klassen Name (Vorname, Mittelname und Nachname) und Adresse (Straße, Hausnummer, PLZ und Stadt) zusammen. Die Klasse Mitglied erbt von der Klasse Person.

Wie muss ich die Erstellung des Objekts gestalten, damit ich ein Mitglied mit den Attributwerten der Person erstelle?
Wenn ich jetzt ein Mitglied erstelle wird ja der Defaultkonstruktor aufgerufen von der Klasse Person.

Hier nochmal die Klassen:

Java:
public final class Name implements Comparable {
      private String firstName;
      private char mi;
      private String lastName;

      /** Construct a name with firstName, mi, and lastName */
      public Name(String firstName, char mi, String lastName) {
        this.firstName = firstName;
        this.mi = mi;
        this.lastName = lastName;
      }
    
    
    /** Return firstName */
      public String getFirstName() {
        return firstName;
      }

      /** Return middle name initial */
      public char getMi() {
        return mi;
      }

      /** Return lastName */
      public String getLastname() {
        return lastName;
      }

      /** Obtain full name */
      public String getFullName() {
        return firstName + ' ' + mi + ' ' + lastName;
      }
    
    public final class Address {
      private String street;
      private int streetNumber;
      private String zip;
      private String city;
    
      
      /** Create an address with street, streetnumber, zip, city */
      public Address(String street, int streetNumber, String zip, String city) {
        this.street = street;
        this.streetNumber = streetNumber;
        this.city = city;
        this.zip = zip;
      }
        
        /** Get full address */
      public String getFullAddress() {
        return street + ' ' + streetNumber + ", " + zip + " "+city + '\n';
      }
        
        public class Person {
      private Name name;
      private Address address;
      private LocalDate date;
      private Geschlecht gesch;
      
      private enum Geschlecht {male, female , diverse}


      /** Construct a person with default properties */
      public Person() {
        this(new Name("Max",'a',"Mustermann"),
          new Address("Musterstr", 35, "99999", "Stadt"),
          LocalDate.now(),
          Geschlecht.diverse);
          
      }
    
    
      /** Construct a person with specified name and address */
      public Person(Name name, Address address, LocalDate date, Geschlecht gesch) {
        this.name = name;
        this.address = address;
        this.date=date;
        this.gesch=gesch;
        
      }
            
         public String toString() {

        return '\n' + name.getFullName() + '\n' +
          address.getFullAddress()  +gesch +'\n';
      }

            public class Main {

    public static void main(String[] args) {


        Mitglied mg=new Mitglied("123",...,...,...);
        
        System.out.println(mg);
        
    }
}
 
Du darfst dann natürlich nicht den Konstruktor ohne Parameter verwenden (Das ist nicht der Default Konstruktor. Der Default Konstruktor ist ein Konstruktor ohne Parameter, der automatisch hinzugefügt wird, wenn es keinen anderen konstruktor gibt. JLS 8.8.9).

Person hat ein Konstruktor, der ja name, Adresse und so weiter als Parameter hat. Diesen Konstruktor musst du dann verwenden.
 
Na ja aber wenn ich eine Person erstelle hab ich ja keine Daten vom Mitglied. Im möchte eigentlich ein Mitglied erstellen mit den Attributen vom Mitglied und natürlich auch mit den personenbezogenen Daten.
 
Du hast die Klasse Mitglied nicht gezeigt meine ich. Aber da solltest Du dann natürlich im Konstruktor auch die Daten als Parameter bekommen und dann kannst Du im Konstruktor von mitglied den Konstruktor von Person mittels super(....) aufrufen. Den Aufruf selbst hattest Du ja schon skizziert in Deiner main:
Mitglied mg=new Mitglied("123",...,...,...);
 

Zurück
Oben