> For the complete documentation index, see [llms.txt](https://opu.gitbook.io/oop/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://opu.gitbook.io/oop/2019-2020-archive/arkhiv-1/lectures/20.-perechisleniya.md).

# 20. Перечисления

## Механизм перечислений

Механизм перечислений был добавлен в JDK версии 5 и позволяет удобно хранить и работать с так называемыми "категориальными данными".

Категориальные данные - это данные с ограниченным числом унекальных значений или категорий. Примеры категориальных данных:

* месяц год (12 значений: январь, февраль и так далее);
* вероисповедание (православие, католицизм, ислам и так далее);
* день недели (понедельник, вторник, среда и так далее).

Рассмотрим пример. Для информационной системы "Электронный институт" необходимо создать класс сотрудника кафедры `DepartmentMember`, в котором, среди прочих атрибутов, есть атрибут `position` (должность). Предположим, что сотрудники кафедры могут занимать одну из следующих должностей:

* Engineer;
* Assistant;
* Lecturer;
* Senior Lecturer;
* Professor.

Каким образом мы можем представить эти данные в компьютерной программе? Самый очевидный вариант - использовать строки.

```
```

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

```
```

Например, должность старшего преподавателя может быть записана как "ст. преп., ст. преподаватель, ст. пр." и так далее, не говоря про возможные орфографические ошибки. С точки зрения формальной логики, это все разные категории должностей и вы не сможете группировать или фильтровать сотрудников кафедры по полю "должность".

Второй вариант - создать несколько статических целочисленных констант, которые можно использовать вместо строк.

```
```

Теперь мы сможем использовать именованные константы вместо строго фиксированных строк.

```
```

Использование именованных констант позволяет отчасти избавиться от недостатков предыдущего подхода, но и этот вариант не является приемлемым. Ничто не мешает клиентскому коду при создании объекта указать целое  число вместо именованной константы, осуществлять проверку ввода - достаточно трудоемкая задача, если в классе предусмотрено более одного категориального значения, будет тяжело определять, какие конкретно именованные константы необходимо использовать. К тому же, при использовании конструктора или сеттера поля `position`, нет никакого указания на необходимость использования именованных констант, программист сам должен догадаться о наличии нужных констант или читать сопроводительную документацию.

```
```

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

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

```
```

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

Обратите внимание на синтаксис перечисления. Перечисление является классом, но очень своеобразным. Вместо ключевого слова `class` используется ключевое слово `enum` (от слова enumeration - перечисление). В самом простом варианте, в перечислении просто указывается список констант, через запятую.

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

```
```

В данном примере, экземпляр перечисления хранит строку с цветом.
