Zum Inhalt

Aufzählungstypen (enum)

Motivation

Angenommen, Sie wollen mithilfe einer Variablen eine festgelegte Menge an Zuständen beschreiben, z.B.

String Tag = "MONTAG"   // kann auch Werte "Dienstag" usw. annehmen
int Tag = 0;            // Magic Number für "Montag"

Das Problem: - die Variablen können auch beliebige andere Werte (aus dem jeweiligen Wertebereich) annehmen, z.B. Tag = "hallo" oder Tag=4711, - Magic Numbers sollen vermieden werden → meistens schlechte Lesbarkeit

public class TicTacToe 
{
    int[][] field;

    TicTacToe()
    {
        field = new int[3][3];
        for(int i=0; i<field.length; i++)
            for(int j=0; j<field[i].length; j++)
                field[i][j]=0;
    }

    void makeMove(int i, int j, int player)
    {
        if(field[i][j]==0 && player==1 || player==2)    
            field[i][j]=player;
    }
}
  • Zustände EMPTY (0), RED (1), BLACK (2) verschlüsselt → magic numbers
  • field[i][j] könnte auch beliebige andere int-Werte annehmen
  • Code nahezu unlesbar

Erster Verbesserungsversuch: Konstanten

public class TicTacToe 
{
    int[][] field;
    static final int EMPTY = 0;
    static final int RED = 1;
    static final int BLACK = 2;

    TicTacToe()
    {
        field = new int[3][3];
        for(int i=0; i<field.length; i++)
            for(int j=0; j<field[i].length; j++)
                field[i][j]=EMPTY;
    }

    void makeMove(int i, int j, int player)
    {
        if(field[i][j]==EMPTY && player==RED || player==BLACK)  
            field[i][j]=player;
    }
}
  • etwas besser, aber immer noch beliebige Werte für field[i][j] möglich

Der Aufzählungstyp enum

Anforderungen:

  • eigener Datentyp
  • endliche Anzahl an Zuständen bzw. Werten
  • leserliche Bezeichnung der Werte

Lösung: - Enumerations (sog. Aufzählungstypen) - Schlüsselwort enum

Syntax:

    enum TypName {WERT1, WERT2, WERT3};

Verwendung: - TypName nun als Datentyp verwendbar, z.B. TypName[][] - Zugriff auf Werte über statische Punktschreibweise, z.B. TypName.WERT1

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
public class TicTacToe 
{
    enum State {EMPTY, RED, BLACK};
    State[][] field;

    TicTacToe()
    {
        field = new State[3][3];
        for(int i=0; i<field.length; i++)
            for(int j=0; j<field[i].length; j++)
                field[i][j]=State.EMPTY;
    }

    void makeMove(int i, int j, State player)
    {
        if(field[i][j]==State.EMPTY && player!=State.EMPTY)     
            field[i][j]=player;
    }
}
  • typsicher
  • rot und schwarz über State.RED und State.BLACK erreichbar
  • andere Zustände nicht möglich

Details:

  • alle enum erben implizit von java.lang.Enum
  • enum sind Referenztypen
  • die Konstanten (Werte) in enum sind automatisch static und final
  • == kann verwendet werden (auch switch()); equals() gibt es aber auch
1
2
3
4
5
6
7
8
State s = State.EMPTY;  // s = 0 oder s = "rot" oder so geht nicht 
                        //-> typsicher
switch(s)
{
    case EMPTY:     System.out.println("leeres Feld"); break;
    case RED:   System.out.println("roter Stein"); break;
    case BLACK:     System.out.println("schwarzer Stein Feld"); break;
}

Weiteres:

  • auch Definition von Methoden möglich
  • toString(), equals() usw. aus Object können überschrieben werden
  • Konstanten können mit Attributen versehen werden (dann noch privater Konstruktor notwendig)
  • Zugriff auf das Array von Konstanten mithilfe von values()
enum Farben {
    KREUZ(12), PIK(11), HERZ(10), KARO(9);
    private int farbwert;

    private Farben(int wert)
    {
        this.farbwert=wert;
    }   

    @Override
    public String toString()
    {
        char c = ' ';
        switch(this)
        {
            case KREUZ  : c ='\u2663';  break;
            case PIK    : c ='\u2664';  break;
            case HERZ   : c ='\u2665';  break;
            case KARO   : c ='\u2666';  break;
        }
        return String.valueOf(c);
    }
}
enum Karten {
    AS(11), ZEHN(10), NEUN(0), ACHT(0), SIEBEN(0), K(4), D(3), B(2);
    private int kartenwert;

    private Karten(int wert)
    {
        this.kartenwert=wert;
    }

    @Override
    public String toString()
    {
        String s = "";
        switch(this)
        {
            case AS     : s ="A";   break;
            case ZEHN   : s ="10";  break;
            case NEUN   : s ="9";   break;
            case ACHT   : s ="8";   break;
            case SIEBEN : s ="7";   break;
            case K      : s ="K";   break;
            case D      : s ="D";   break;
            case B      : s ="B";   break;
        }
        return s;
    }
}
Ausführliches Beispiel - Skat.java
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
package vorbereitungen.enums;

import java.util.Arrays;
import java.util.Random;

public class Skat {
    Karte[] p1;
    Karte[] p2;
    Karte[] p3;
    Karte[] skat;

    enum Karten {
        AS(11), ZEHN(10), NEUN(0), ACHT(0), SIEBEN(0), K(4), D(3), B(2);
        private int kartenwert;

        private Karten(int wert)
        {
            this.kartenwert=wert;
        }

        @Override
        public String toString()
        {
            String s = "";
            switch(this)
            {
                case AS     : s ="A";   break;
                case ZEHN   : s ="10";  break;
                case NEUN   : s ="9";   break;
                case ACHT   : s ="8";   break;
                case SIEBEN : s ="7";   break;
                case K      : s ="K";   break;
                case D      : s ="D";   break;
                case B      : s ="B";   break;
            }
            return s;
        }
    }

    enum Farben {
        KREUZ(12), PIK(11), HERZ(10), KARO(9);
        private int farbwert;

        private Farben(int wert)
        {
            this.farbwert=wert;
        }   

        @Override
        public String toString()
        {
            char c = ' ';
            switch(this)
            {
                case KREUZ  : c ='\u2663';  break;
                case PIK    : c ='\u2664';  break;
                case HERZ   : c ='\u2665';  break;
                case KARO   : c ='\u2666';  break;
            }
            return String.valueOf(c);
        }
    }

    class Karte {
        Karten k;
        Farben f;

        Karte(Karten k, Farben f)
        {
            this.k=k;
            this.f=f;
        }

        @Override
        public Karte clone()
        {
            return new Karte(this.k,this.f);
        }

        @Override
        public String toString()
        {
            return f.toString()+k.toString()+" ";
        }

    }

    class Deck {
        Karte[] deck;

        Deck()
        {
            deck = new Karte[32];
            int index = 0;
            for(Farben f: Farben.values())
            {
                for(Karten k:Karten.values())
                {
                    deck[index++] = new Karte(k,f);
                }
            }
        }

        @Override
        public String toString()
        {
            String s = "";
            for(int i=0; i<deck.length; i++)
            {
                s += deck[i].f.toString() + deck[i].k.toString() +" ";
                if(i==7 || i==15 || i==23 || i==31) s+="\n";
            }
            return s;
        }

        public void print()
        {
            System.out.println(this.toString());
        }

    }

    Skat()
    {
        p1 = new Karte[8];
        p2 = new Karte[8];
        p3 = new Karte[8];
        skat = new Karte[2];    
    }

    boolean existsFalse(boolean[] b)
    {
        for(int i=0; i<b.length; i++)
        {
            if(!b[i]) return true;
        }
        return false;
    }

    public void geben()
    {
        Deck d = new Deck();
        Random r = new Random();    
        boolean[] b = new boolean[32]; 
        Arrays.fill(b, false);
        int indexP1 = 0, indexP2 = 0, indexP3 =0, indexSkat = 0;
        int zz = r.nextInt(32);
        while(existsFalse(b))
        {
            while(b[zz])
            {
                zz = r.nextInt(32);
            }
            b[zz] = true;
            if(indexP1<8)
            {
                p1[indexP1++] = d.deck[zz].clone();
            }
            else if(indexP2<8)
            {
                p2[indexP2++] = d.deck[zz].clone();
            }
            else if(indexP3<8)
            {
                p3[indexP3++] = d.deck[zz].clone();
            }
            else if(indexSkat<2)
            {
                skat[indexSkat++] = d.deck[zz].clone();
            }
        }
    }

    public void sortieren()
    {

    }

    public void print()
    {
        System.out.print("Spieler 1 : ");
        for(Karte k : p1) System.out.print(k.toString()+" ");
        System.out.println();
        System.out.print("Spieler 2 : ");
        for(Karte k : p2) System.out.print(k.toString()+" ");
        System.out.println();
        System.out.print("Spieler 3 : ");
        for(Karte k : p3) System.out.print(k.toString()+" ");
        System.out.println();
        System.out.print("Skat      : ");
        for(Karte k : skat) System.out.print(k.toString()+" ");
        System.out.println();
    }

    public static void main(String[] args) {
        Skat s = new Skat();
        s.geben();
        s.print();

    }

}