Java. Использование перечислений как классов

Использование перечислений как классов. Примеры объявления перечислений содержащих конструкторы, внутренние поля, методы


Содержание


Поиск на других ресурсах:

1. Особенности использования перечислений в качестве классов.  Использование конструкторов, полей и методов в перечислениях

Все перечисления, объявляемые в программе на языке Java, являются типами классов и унаследованы от класса Enum. Такое наследование значительно расширяет возможности перечислений. Перечисления могут содержать конструкторы, интерфейсы, внутренние поля, методы и т.п. Использование различных составляющих в теле перечисления работает так же, как и в классах.
При объявлении экземпляра перечисления не требуется использовать оператор new. Каждая именованная константа перечисления является объектом класса своего перечисления. Это означает, что при объявлении конструктора в перечислении этот конструктор вызывается каждый раз при создании константы перечисления.

Конструктор в перечислении используется так же, как и в классе. С помощью конструктора инициализируются значения именованных констант перечисления. Перечисление может содержать произвольное количество перегруженных конструкторов.

В упрощенном варианте общая форма объявления и использования конструктора в перечислении следующая:

enum EnumName {
  constant1(arguments1),
  constant2(arguments2),
  ...
  constantN(argumentsN);

  // Конструктор
  EnumName(list_of_parameters) {
    // ...
  }
}

здесь

  • EnumName – имя типа перечисления;
  • constant1, constant2, constantN – именованные константы из перечисления, принимающие соответственно значения аргументов arguments1, agruments2, argumentsN;
  • EnumName(list_of_parameters) – конструктор перечисления, получающий перечень параметров list_of_parameters.

Поля (внутренние переменные) в перечислении, в основном, применяются для сохранения значений именованных констант. Методы в перечислении позволяют проводить различные операции, вычисления над полями и получать доступ к именованным константам. В перечислениях не запрещается использовать любое количество полей и методов для проведения вычислений или других действий.

 

2. Примеры использования конструкторов, полей и методов в перечислениях. Инициализация данных в перечислении
2.1. Пример установки количества дней в месяце для именованных констант

Условие задачи. Задано перечисление Months. С помощью конструктора задать каждому месяцу значение количества дней в этом месяце.

Решение.

// Перечисление, описывающее месяцы года
enum Months {
  // Именованные константы - месяцы года
  January(31), February(28), March(31), April(30), May(31), June(30),
  July(31), August(31), September(30), October(31), November(30), December(31);

  // Конструктор, необходимый для инициализации
  // именованных констант (Jauary, February, ...) целочисленными значениями
  Months(int nDays) {
    this.nDays=nDays;
  }

  // Поле, сохраняющее количество дней,
  // например, для константы January(31) значение nDays = 31
  private int nDays;

  // Метод, возвращающий количество дней
  public int getNDays() { return nDays; }
}

public class TrainEnumerations {

  public static void main(String[] args) {
    // Создать экземпляр типа Months и инициализировать его значением
    Months mn = Months.April;

    // Вызвать количество дней в константе mn.April
    System.out.println(mn.getNDays());

    // Вызвать количество дней в константе Months.September
    System.out.println(Months.September.getNDays());
  }
}

Объясним выполнение вышеприведенного кода. В вышеприведенном примере каждая константа инициализируется целочисленным значением (January(31), February(28), …) благодаря использованию конструктора

Months(int nDays) {
  this.nDays=nDays;
}

Значение количества дней хранится в скрытом (private) внутреннем поле

private int nDays;

Для того чтобы считывать поле nDays в клиентском коде, нужно в теле перечисления Months создать общедоступный метод

// Метод, возвращающий количество дней
public int getNDays() { return nDays; }

Вышеприведенный подход позволяет корректно сохранять и получать значения любых типов в именованных константах перечисления.

Результат выполнения программы

30
30

 

2.2. Пример использования перечисления, сохраняющего константы типа double

Условие задачи. Продемонстрировать использование известных математических констант в перечислении MathConstants. Использовать константы для проведения вычислений.

Решение. Как известно, каждая константа перечисления является объектом (экземпляром) типа этого перечисления. Поэтому, чтобы сохранять константы типа double, нужно создать соответствующий конструктор. Этот конструктор будет получать параметр значения типа double, который будет инициализировать константу.

Для каждой константы нужно сохранять значение, поэтому, в код перечисления вводится дополнительная внутренняя private-переменная, которая это значение будет сохранять.

Текст программы, решающей данную задачу, следующий

import java.util.Scanner;

// Перечисление, содержащее математические константы типа double.
enum MathConstants {
  Pi(3.1415), Exp(2.71), G(9.81);

  // Внутреннее поле, которое сохраняет значение константы
  private double value;

  // Конструктор - необходим для инициализации
  // констант значениями, например: Pi(3.1415)
  MathConstants(double x) {
    value = x;
  }

  // Метод необходим для получения значения константы
  public double Value() {
    return value;
  }
}

public class TrainEnumerations {

  public static void main(String[] args) {

    // Использование констант с плавающей запятой в перечислениях
    // 1. Объявить перечисление
    MathConstants mc;

    // 2. Чтобы использовать константу G, необходимо вызвать метод Value().
    mc = MathConstants.G;
    System.out.println("G = " + mc.Value()); // G = 9.81

    // 3. Использовать константу Pi
    // для вычисления объема шара по введенному радиусу
    Scanner inputDouble = new Scanner(System.in);
    System.out.print("radius = ");
    double radius = inputDouble.nextDouble();
    double volume = 4.0/3*MathConstants.Pi.Value()*radius*radius*radius;
    System.out.println("volume = " + volume);
  }
}

Тестовый пример

G = 9.81
radius = 4
volume = 268.07466666666664

 

2.3. Пример объявления перечисления, в котором используются два конструктора.

Константы в перечислении могут инициализироваться разными способами. Для этого объявляется несколько подходящих конструкторов.
В примере, с целью демонстрации, инициализируются значения именованных констант разными способами.

// Перечисление, в котором именованные константы инициализируются разными конструкторами
enum Character {
  // Именованные константы
  A('A'), // вызывается конструктор с 1 параметром
  B('B'), // вызывается конструктор с 1 параметром
  Enter('\n'), // вызывается конструктор с 1 параметром
  SpaceBar; // вызывается конструктор без параметров

  // Конструктор, получающий один параметр
  Character(char _symbol) {
    symbol = _symbol;
  }

  // Конструктор без параметров, устанавливает символ "пробел"
  Character() {
    symbol = ' '; // клавиша пробел
  }

  // Внутренняя переменная, сохраняющая символ
  private char symbol;

  // Метод доступа к переменной symbol
  public char getSymbol() { return symbol; }
}

public class TrainEnumerations {

  public static void main(String[] args) {

    // 1. Задать экземпляр перечисления типа Character
    Character ch = Character.B;

    // 2. Вывести значение экземпляра ch
    System.out.println(ch.getSymbol()); // B
  }
}

 

2.4. Пример объявления перечисления, в котором конструктор получает 2 параметра

В примере объявляется перечисление PaperSize, описывающее форматы писем по их размерам. Размер каждого листа задается двумя параметрами: шириной и высотой. Соответственно, константы из перечисления получают два значения. Для инициализации этих значений в перечислении объявляется конструктор, получающий 2 параметра.

Текст демонстрационной программы следующий

// Перечисление, описывающее форматы бумаги A1, A2, A3, A4, ...
enum PaperSize {
  // Форматы листов
  A1(594, 841),
  A2(420, 594),
  A3(297, 420),
  A4(210, 297),
  A5(148, 210),
  A6(105, 148),
  A7(74, 105);

  // Конструктор с двумя параметрами
  PaperSize(int width, int height) {
    this.width = width;
    this.height = height;
  }

  // Внутренние переменные – размеры листа бумаги
  private int width, height;

  // Методы доступа
  public int getWidth() { return width; }
  public int getHeight() { return height; }
}

public class TrainEnumerations {
  public static void main(String[] args) {
    // Использование перечисления PaperSize
    PaperSize ps = PaperSize.A2;

    // Вывести ширину и высоту
    System.out.println("Format " + ps.name() + ":");
    System.out.println("width = " + ps.getWidth() +
" height = " + ps.getHeight());
  }
}

Результат выполнения программы

Format A2:
width = 420 height = 594

 


Связанные темы