Aufzählung

1. Aufzählungstyp (Enumerated Type)

Aufzählungen in Pascal sind gut gekapselte undurchsichtige Typen und werden in der täglichen Entwicklung deutlich häufiger verwendet als Aufzählungen anderer Programmiersprachen.

Grundlegende Definitionsweise

type
  TAnimalKind = (akDuck, akCat, akDog);

Vereinbarung: Jede Aufzählungskonstante erhält ein zweibuchstabiges Präfix aus der Typabkürzung

  • ak = Animal Kind (Abkürzung von TAnimalKind)
  • Zweck: Aufzählungskonstanten liegen standardmäßig im globalen Namensraum der Unit. Das Präfix senkt die Wahrscheinlichkeit von Namenskonflikten mit anderen Variablen und Typen stark ab.

Das vorangestellte T bei TAnimalKind ist syntaktisch optional, es handelt sich lediglich um eine Branchenkonvention. Wir empfehlen, es zu verwenden, damit man sofort erkennt, dass es sich um einen Aufzählungstyp handelt.

type
  AnimalKind = (akDuck, akCat, akDog); // Ohne T, syntaktisch zulässigCode-Sprache: JavaScript (javascript)

Zusätzliche Hinweise:

  1. Gleichnamige Bezeichner führen nicht sofort zu einem Kompilierfehler; verschiedene Units dürfen identische Namen verwenden;
  2. Trotzdem sollte man Namenskonflikte vermeiden, um Lesbarkeit und globale Suchvorgänge (grep) zu erleichtern.

Gültigkeitsbereichsaufzählungen (eingeschränkte Aufzählungen, {$scopedenums on})

Die Compiler-Direktive {$scopedenums on} lagert Aufzählungskonstanten in den zugehörigen Typ aus und verschmutzt nicht mehr den globalen Namensraum

Standardmäßig deaktiviert
{$ifdef FPC} {$mode objfpc} {$H+} {$endif}
{$codepage utf8}
program EnumDemo;

type TAnimalKind = (akDuck, akCat);

var k: TAnimalKind;

begin
  k := akDuck; // Konstante direkt verwenden, ohne TAnimalKind.
  WriteLn(k); //Gibt akDuck aus
end.Code-Sprache: PHP (php)

Wie bereits gesagt, beginnt die Ausführung des Codes ab dem Schlüsselwort begin.

Das Präfix ak ist empfehlenswert, um Konflikte zu vermeiden; das Weglassen verursacht keinen Fehler.

{$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-Sprache: PHP (php)

Bei aktiviertem {$scopedenums on} muss immer „Typname.“ vorangestellt werden

  1. Der Zugriff erfordert zwingend die Typqualifizierung: TAnimalKind.akDuck
  2. Das ak-Präfix entfällt, die Konstanten lassen sich einfach als Duck, Cat, Dog schreiben
{$scopedenums on}
type
  TAnimalKind = (Duck, Cat, Dog);
var
  Kind: TAnimalKind;
begin
  Kind := TAnimalKind.Duck; // Typqualifizierung ist Pflicht
end;Code-Sprache: PHP (php)

Ohne vorangestellten Typnamen

{$ifdef FPC} {$mode objfpc} {$H+} {$endif}
{$codepage utf8}
{$scopedenums on}
program EnumDemo;

type TAnimalKind = (Duck, Cat);
var k: TAnimalKind;
begin
  k := Duck; // Fehlt TAnimalKind.
  WriteLn(k);
end.Code-Sprache: PHP (php)

Es entsteht ein Kompilierfehler

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-Sprache: CSS (css)

Fügt man die Typqualifizierung hinzu

{$ifdef FPC} {$mode objfpc} {$H+} {$endif}
{$codepage utf8}
{$scopedenums on}
program EnumDemo;

type TAnimalKind = (Duck, Cat);
var k: TAnimalKind;
begin
  k := TAnimalKind.Duck; // Mit vollständiger Typqualifizierung
  WriteLn(k);
end.Code-Sprache: PHP (php)

lässt sich der Code fehlerfrei kompilieren

Explizite Typumwandlung zwischen Aufzählungen und Ganzzahlen

Aufzählungen zählen zu den undurchsichtigen Typen; eine direkte Zuweisung zwischen Aufzählungen und Ganzzahlen ist nicht erlaubt, eine manuelle Umwandlung ist erforderlich:

  1. Aufzählung → Ganzzahl: Ord(AufzählungsVariable)
  2. Ganzzahl → Aufzählung: Explizite Typumwandlung TAnimalKind(Ganzzahlwert)
  3. Prüfe vor der Umwandlung stets den gültigen Wertebereich: gültiges Intervall 0 ~ Ord(High(AufzählungsTyp))
type
  TAnimalKind = (akDuck, akCat, akDog);
var
  Kind: TAnimalKind;
  Num: Integer;
begin
  Kind := akCat;
  Num := Ord(Kind); // akCat hat den Ordinalwert 1, Num=1

  Num := 2;
  // Zuerst Wertebereich prüfen, dann umwandeln
  if (Num >= 0) and (Num <= Ord(High(TAnimalKind))) then
    Kind := TAnimalKind(Num);
end;Code-Sprache: 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-Sprache: PHP (php)

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert