一、列挙型(Enumerated Type)
Pascalの列挙型はカプセル化に優れた不透明型で、実務開発では他言語の列挙型より頻繁に使用されます。
基本的な定義記法
type
TAnimalKind = (akDuck, akCat, akDog);
コーディング規約:列挙定数名に型名2文字略称のプレフィックスを付ける
ak= Animal Kind(TAnimalKindの略称)- 役割:列挙定数は既定でユニットのグローバル名前空間に属するため、プレフィックスを付けることで他変数・型との名前衝突を大幅に抑えられます。
TAnimalKindの先頭Tは構文上省略可能ですが、業界標準の規則のため付記を推奨します。一目で列挙型と判断できるようになります。
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)

列挙型
Previous: 複数値条件判定(case文)