1. Перечислимые типы (Enumerated Type)
Перечислимые типы Pascal — это хорошо инкапсулированные непрозрачные типы, в повседневной разработке они встречаются значительно чаще перечислений из других языков.
Базовый синтаксис объявления
type
TAnimalKind = (akDuck, akCat, akDog);
Соглашение по именованию: для констант перечисления используется двухбуквенный префикс, сокращение названия типа
ak= Animal Kind (сокращение от TAnimalKind)- Значение: по умолчанию константы перечисления находятся в глобальном пространстве имен модуля. Префикс сильно снижает риск конфликтов имен с переменными и пользовательскими типами.
Буква T в начале TAnimalKind синтаксически необязательна, это просто стандарт индустрии. Рекомендуется оставлять её, чтобы сразу понять, что это перечислимый тип.
type
AnimalKind = (akDuck, akCat, akDog); // Без префикса T, синтаксис корректенCode language: JavaScript (javascript)
Дополнительные замечания:
- Одинаковые идентификаторы не вызывают немедленной ошибки компиляции; разные модули могут содержать одинаковые имена;
- Тем не менее для читаемости кода и удобства глобального поиска (grep) стоит самостоятельно избегать конфликтов имен.
Перечисления с ограниченной областью видимости ({$scopedenums on})
Директива компилятора {$scopedenums on} помещает константы перечисления внутрь родительского типа, не загрязняя глобальное пространство имен
По умолчанию выключено
{$ifdef FPC} {$mode objfpc} {$H+} {$endif}
{$codepage utf8}
program EnumDemo;
type TAnimalKind = (akDuck, akCat);
var k: TAnimalKind;
begin
k := akDuck; // Константа используется напрямую, без префикса TAnimalKind.
WriteLn(k); //Выводится akDuck
end.Code language: PHP (php)
Как мы говорили раньше, выполнение кода начинается с ключевого слова begin.

Использовать префикс ak — хорошая практика для предотвращения конфликтов, но даже без него ошибок не будет.
{$ifdef FPC} {$mode objfpc} {$H+} {$endif}
{$codepage utf8}
program EnumDemo;
type TAnimalKind = (Duck, Cat);
var k: TAnimalKind;
begin
k := Duck;
WriteLn(k);//Duck
end.Code language: PHP (php)

При включенном {$scopedenums on} обязательно указывать «ИмяТипа.»
- При обращении нужен квалификатор типа:
TAnimalKind.akDuck - Префикс ak больше не нужен, константы можно писать просто Duck, Cat, Dog
{$scopedenums on}
type
TAnimalKind = (Duck, Cat, Dog);
var
Kind: TAnimalKind;
begin
Kind := TAnimalKind.Duck; // Квалификатор типа обязателен
end;Code language: PHP (php)
Если не добавлять квалификатор типа
{$ifdef FPC} {$mode objfpc} {$H+} {$endif}
{$codepage utf8}
{$scopedenums on}
program EnumDemo;
type TAnimalKind = (Duck, Cat);
var k: TAnimalKind;
begin
k := Duck; // Отсутствует TAnimalKind.
WriteLn(k);
end.Code language: PHP (php)
Появится ошибка компиляции
D:\fpcdemo>fpc mydemo.dpr
Free Pascal Compiler version 3.2.2 [2021/05/15] for i386
Copyright (c) 1993-2021 by Florian Klaempfl and others
Target OS: Win32 for i386
Compiling mydemo.dpr
mydemo.dpr(9,8) Error: Identifier not found "Duck"
mydemo.dpr(11,4) Fatal: There were 1 errors compiling module, stopping
Fatal: Compilation aborted
Error: C:\FPC\3.2.2\bin\i386-Win32\ppc386.exe returned an error exitcodeCode language: CSS (css)
Если добавить квалификатор типа
{$ifdef FPC} {$mode objfpc} {$H+} {$endif}
{$codepage utf8}
{$scopedenums on}
program EnumDemo;
type TAnimalKind = (Duck, Cat);
var k: TAnimalKind;
begin
k := TAnimalKind.Duck; // Полный квалификатор типа
WriteLn(k);
end.Code language: PHP (php)
Код скомпилируется без ошибок

Явное преобразование между перечислениями и целыми числами
Перечислимые типы относятся к непрозрачным типам, напрямую присваивать целые числа и перечисления друг другу нельзя, требуется ручное преобразование:
- Перечисление → Целое число:
Ord(ПеременнаяПеречисления) - Целое число → Перечисление: явное преобразование
TAnimalKind(ЦелоеЗначение) - Перед преобразованием числа в перечисление обязательно проверяйте диапазон: допустимый интервал
0 ~ Ord(High(ТипПеречисления))
type
TAnimalKind = (akDuck, akCat, akDog);
var
Kind: TAnimalKind;
Num: Integer;
begin
Kind := akCat;
Num := Ord(Kind); // Порядковый номер akCat равен 1, Num=1
Num := 2;
// Сначала проверяем диапазон, затем преобразуем
if (Num >= 0) and (Num <= Ord(High(TAnimalKind))) then
Kind := TAnimalKind(Num);
end;Code language: JavaScript (javascript)
{$ifdef FPC} {$mode objfpc} {$H+} {$endif}
{$codepage utf8}
program EnumDemo;
type
TAnimalKind = (akDuck, akCat, akDog);
var
Kind: TAnimalKind;
Num: Integer;
begin
Kind := akCat;
Num := Ord(Kind); // akCat index is 1,Num=1
Num := 2;
if (Num >= 0) and (Num <= Ord(High(TAnimalKind))) then
Kind := TAnimalKind(Num);
WriteLn(Num);//2
end.Code language: PHP (php)
