Stałe wyliczeniowe w Delphi

Użycie stałych wyliczeniowych znacznie ułatwia programowanie i sprawia że kod staje się bardziej czytelny. Czym są stałe wyliczeniowe? Otóż to nic innego, jak zbiory ponazywanych elementów, które mogą przyjmować jakieś wartości całkowitoliczbowe.
Prostym przykładem wyliczenia niech będzie zmienna typu Boolean, która może przyjmować dwie wartości True lub False. Jeżeli do zmiennej tego typu zechcemy przypisać inną wartość spowoduje to błąd kompilatora.
Bardziej obszerny artykuł na temat stałych wyliczeniowych został zamieszczony w dziale .NET C# -> Stałe wyliczeniowe (Enum) w .NET. W artykule poświęconym Delphi skupię się tylko na najważniejszych aspektach stałych wyliczeniowych.

Deklarowanie zmiennych typu wyliczeniowego

Kiedy chcemy użyć zmiennej typu wyliczeniowego musimy zdefiniować zakres możliwych do użycia elementów po czym definiujemy własny typ danych zawierający utworzone elementy.
Język Delphi umożliwia programiście tworzenie niestandardowych wyliczeń. Chcąc na przykład utworzyć wyliczenie zawierające dni tygodnia deklarujemy je jak poniżej:

type TDniTygodnia = (Poniedzialek,
                     Wtorek,
                     Sroda,
                     Czwartek,
                     Piatek,
                     Sobota,
                     Niedziela);

Enumerator czyli wyliczenie jest definiowany za pomocą słowa kluczowego type. Po nim podajemy jego nazwę oraz w nawiasach piszemy jakie wartości on przyjmuje. W wyliczeniu TDniTygodnia zdefiniowano siedem imiennych stałych odpowiadających wartościom liczbowym. Domyślnie pierwszy element (Poniedzialek) jest ustawiany na wartość zero (0) a pozostałe zgodnie z progresją n+1. W zwyczaju programistów Delphi przyjęło się już, że każdy nowy typ danych poprzedzony jest dużą literą T — ja nie zamierzam od tej reguły odstępować stąd nazwa wyliczenia TDniTygodnia.

Wartości początkowe można zmieniać wedle własnego upodobnienia np.

type TDniTygodnia = (Poniedzialek = 1,
                     Wtorek,
                     Sroda = 5,
                     Czwartek,
                     Piatek,
                     Sobota,
                     Niedziela = 0);

Jak widać na powyższym przykładzie kolejność w wyliczeniach nie musi być sekwencyjna, wartości unikatowe też nie są wymagane.
Trzeba zauważyć, że elementy którym nie przydzieliliśmy konkretnej wartości nadal będą automatycznie rosły zgodnie z progresją +1 (w odniesieniu do elementu poprzedniego).
Dni tygodnia dla powyższego wyliczenia będą miały zatem następujące wartości:

Poniedzialek = 1,
Wtorek = 2,
Sroda = 5,
Czwartek = 6,
Piatek = 7,
Sobota = 8,
Niedziela = 0,

Pobieranie wartości składowych wyliczenia

Zadeklarujmy wyliczenie jak poniżej:

type TDniTygodnia = (Poniedzialek = 1,
                     Wtorek,
                     Sroda,
                     Czwartek,
                     Piatek,
                     Sobota,
                     Niedziela);

Wartości elementów wyliczenia będą mieścić się w przedziale od 1 do 7. Wartości są całkowitoliczbowe i można je stosować w wyrażeniach zamiast liczb.

function TrwaWeekend(const dzien : TDniTygodnia) : Boolean;
begin
if (dzien > TDniTygodnia.Piatek) then
  Result := True
 else
  Result := False;
end;

Powyższa funkcja sprawdza jaki jest dzień tygodnia i zależnie od tego czy dzień jest "większy" od piątku zwróci wartość True co oznacza, że trwa weekend.
Typy wyliczeniowe bardzo dobrze komponują się z instrukcją case, np:

function NaKtoraDoSzkoly(const dzien : TDniTygodnia) : string;
begin
  case dzien of
      //gdy przekazany w parametrach dzień to Poniedziałek to wykonaj poniższą instrukcję
      TDniTygodnia.Poniedzialek:
        begin
          Result := 'Na 7. Nie lubię poniedziałku';
        end;
      //gdy przekazany w parametrach dzień to Wtorek to wykonaj poniższą instrukcję
      TDniTygodnia.Wtorek:
        begin
          Result := 'Na 7.15';
        end;
      //gdy przekazany w parametrach dzień to Środa, Czwartek lub Piątek
      //to wykonaj poniższą instrukcję
      TDniTygodnia.Sroda..TDniTygodnia.Piatek:
        begin
          Result := 'Na 9';
        end;
      TDniTygodnia.Sobota, TDniTygodnia.Niedziela:
        begin
          Result := 'Wolne od szkoły';
        end;
      else Result := 'Błędnie przekazane dane !!!';
  end;
end;

Pobranie wartości składowej wyliczenia możliwe jest poprzez rzutowanie składowej na typ całkowitoliczbowy np.

function PobierzWartoscWyliczenia(const dzien : TDniTygodnia) : Integer;
begin
 Result := Integer(dzien);
end; 

W drugą stronę odbywa się to w następujący sposób:

function TrwaWeekend() : Boolean;
var dzien : TDniTygodnia ;
begin
dzien := TDniTygodnia(5);

if (dzien > TDniTygodnia.Piatek) then
  Result := True
 else
  Result := False;
end;

W powyższym przykładzie do zmiennej dzien przypisana jest wartość 5, jeżeli wyliczenie będzie posiadać element o takiej wartości, to do zmiennej zostanie przypisana jedna z nazwanych wartości wyliczenia. W przeciwnym wypadku zmienna dzien będzie równa przypisanej wartości.
Zgodnie z powyższym zapis: dzien := TDniTygodnia(50); nie spowoduje błędu kompilatora a zmienna dzien będzie mieć przypisaną wartość 50.

Iterowanie po elementach wyliczenia

Iterowanie po elementach wyliczenia można osiągnąć na kilka sposobów np.

function IterujElementyEnuma() : string;
var dzien : TDniTygodnia;
begin
for dzien := Poniedzialek to Piatek do
   begin
        //jakieś operacje
   end;
end;

Powyższa pętla wykona się pięć razy, analogicznie do ilości dni między poniedziałkiem a piątkiem. Iterowanie po wszystkich elementach wyliczenia można osiągnąć w poniższy sposób:

function IterujElementyEnuma() : string;
var dzien : TDniTygodnia;
begin
for dzien := Low(TDniTygodnia) to High(TDniTygodnia) do
   begin
        //jakieś operacje
   end;
end;

UWAGA. Iterując elementy wyliczenia ważne jest, aby wszystkie jego elementy miały unikatowe wartości, i były zgodne z progresją n+1. Jeżeli będzie inaczej kompilator nie zgłosi błędu ale pętla nie wykona się tyle razy co byśmy chcieli.

type TDniTygodnia = (Poniedzialek = 1,
                     Wtorek,
                     Sroda,
                     Czwartek,
                     Piatek = 1,
                     Sobota,
                     Niedziela);

Na tak zadeklarowanym wyliczeniu pętla wykona się tylko cztery razy ponieważ wartości od piątku do niedzieli powtarzają się, jest to niedopuszczalne.
Podobna sytuacja zaistnieje w poniższym przypadku:

type TDniTygodnia = (Poniedzialek = 1,
                     Wtorek,
                     Sroda,
                     Czwartek,
                     Piatek,
                     Sobota = 30,
                     Niedziela);

W tym przypadku pętla wykona się 31 razy.

Dodaj nowy komentarz

Filtrowany HTML

  • Adresy internetowe są automatycznie zamieniane w odnośniki, które można kliknąć.
  • Dozwolone znaczniki HTML: <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Znaki końca linii i akapitu dodawane są automatycznie.
  • Tekstowe buźki będą zamieniane na ich graficzne odpowiedniki.

Czysty tekst

  • Znaczniki HTML niedozwolone.
  • Adresy internetowe są automatycznie zamieniane w odnośniki, które można kliknąć.
  • Znaki końca linii i akapitu dodawane są automatycznie.
  • Tekstowe buźki będą zamieniane na ich graficzne odpowiedniki.
CAPTCHA
W celu potwierdzenia, że jesteś człowiekiem, prosimy o wykonanie poniższego zadania
Target Image