Co a k čemu jsou výčtové typy?

  • Typově bezpečná cesta, jak vyjmenovat a používat pojmenované konečné výčty prvků.

  • Měsíce v roce (JANUARY, FEBRUARY, …, DECEMBER) nebo dny v týdnu, roční období, světové strany.

  • Všude tam, kde jde o pevnou množinu nemnoha hodnot, které se nějak jmenují.

  • Proměnná určitého výčtového typu může pak v jednu chvíli nabývat jedné hodnoty z daného výčtu.

  • Např. v proměnné season typu Season může být uložena hodnota WINTER.

Příklad definice výčtu

převzato z The Java™ Tutorials Enum Types

Definice výčtového typu "den v týdnu":

public enum Day {
   SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
   THURSDAY, FRIDAY, SATURDAY
}

Příklad použití výčtu

Použití "dne v týdnu":

public void tellItLikeItIs(Day day) {
   switch (day) {
      case MONDAY:
      System.out.println("Mondays are bad.");
      break;
      //
      case FRIDAY:
      System.out.println("Fridays are better.");
      break;
      //
      case SATURDAY: case SUNDAY:
      System.out.println("Weekends are best.");
      break;
      //
      default:
      System.out.println("Midweek days are so-so.");
      break;
   }
}

Alternativy k výčtovému typu

  • Nadefinovat si řadu konstant, např.

public static final int MONDAY = 0;
public static final int TUESDAY = 1;
public static final int WEDNESDAY = 2;
  • Problém s tím je, že nemáme žádnou kontrolu

    typovou

    metoda přijímající den v týdnu musí mít parametr typu int a po zadání libovolného jiného int než z povoleného výčtu nastane problém.

    hodnotovou

    snadno se při kopírování (přidávání dalších) hodnot spleteme a máme dva dny v týdnu stejné — a nikdo na to nemusí přijít.

Výčty technicky

  • Výčtový typ se koncepčně velmi podobá třídě.

  • Ta má však jen pevně daný počet instancí — prvků výčtu.

  • Každý námi definovaný výčtový typ je potomkem třídy java.lang.Enum.

  • Podobně jako jiné třídy má vestavěné metody a může mít další metody, konstruktory apod.

Příklad výčtu s vlastnostmi

převzato z The Java™ Tutorials Enum Types

public enum Planet {
   // pevné hodnoty výčtu, ale vč. nastavení atributů
   MERCURY (3.303e+23, 2.4397e6),
   VENUS   (4.869e+24, 6.0518e6),
   EARTH   (5.976e+24, 6.37814e6),
   // atributy
   private final double mass;   // in kilograms
   private final double radius; // in meters
   // konstruktor nastavující atributy
   Planet(double mass, double radius) {
      this.mass = mass;
      this.radius = radius;
   }
   private double mass() { return mass; }
   private double radius() { return radius; }
   // universal gravitational constant  (m3 kg-1 s-2)
   public static final double G = 6.67300E-11;
   // metody k použití
   double surfaceGravity() {
      return G * mass / (radius * radius);
   }
   double surfaceWeight(double otherMass) {
      return otherMass * surfaceGravity();
   }
   public static void main(String[] args) {
      if (args.length != 1) {
         System.err.println("Usage: java Planet <earth_weight>");
         System.exit(-1);
      }
      double earthWeight = Double.parseDouble(args[0]);
      double mass = earthWeight/EARTH.surfaceGravity();
      // po hodnotách výčtu se dá iterovat
      for (Planet p : Planet.values())
         System.out.printf("Your weight on %s is %f%n",
            p, p.surfaceWeight(mass));
   }
}