Rekordy

Adam Boduch
Rekordy są zorganizowaną strukturą danych, połączona w jedną całość. Jest to jakby zestaw zawierający określone elementy.

1 Rekordy jako parametry funkcji i procedur
2 Deklarowanie rekordu jako zmiennej
3 Metody w rekordach

Rekordy również można przekazywać ? jako zestaw elementów ? do funkcji czy procedur w formie parametru.

Nowe rekordy można deklarować jako nowy typ danych lub jako zmienną przy użyciu słowa kluczowego Record.

type
  TMyRecord = record
    X : Integer;
    Y : Integer;
  end;

Budowa deklaracji rekordu, jak widać, jest specyficzna ? najpierw należy wpisać jego nazwę, a potem po znaku równości słowo kluczowe record (uwaga, brak średnika na końcu!). Następnie wypisujemy elementy, z których ma się składać nasz rekord.

Jako że powyżej zadeklarowaliśmy rekord jako nowy typ danych, należy utworzyć dodatkowo zmienną wskazującą na ten typ. Przy tej okazji przedstawię nowy operator Delphi ? kropkę (.). Do poszczególnych pól rekordu odwołujemy się następująco:

MyRecord.X := 1;

po uprzednim utworzeniu zmiennej wskazującej na rekord.

Po co stosować rekordy? Czasem trzeba przekazać określoną strukturę jako parametr funkcji bądź procedury. Można by oczywiście przekazywać pojedynczo kolejne elementy do procedury, jednak często wygodniej przekazać jeden parametr ? w formie rekordu. Usprawnia to pracę i jest dość często stosowanym elementem programów.

Rekordy jako parametry funkcji i procedur

Napiszmy prosty program, który pobierze dwie liczby wpisane przez użytkownika i przekaże do procedury cały rekord.
Samo przekazanie rekordu do funkcji przebiega w sposób dość prosty:

type
  TMyRecord = record
    X : Integer;
    Y : Integer;
  end;
 
  function Dzielenie(MyRecord : TMyRecord) : Integer;
  begin
    Result := MyRecord.X div MyRecord.Y;
  end;

Delphi wymaga, aby do funkcji Dzielenie został przekazany rekord TMyRecord. Kolejno następuje podzielenie elementu X przez element Y rekordu i zwrócenie wartości dzielenia. Cały program wygląda tak jak na listingu poniżej.

program Recordapp;
 
{$APPTYPE CONSOLE}
 
type
  TMyRecord = record
    X : Integer;
    Y : Integer;
  end;
 
  function Dzielenie(MyRecord : TMyRecord) : Integer;
  begin
    Result := MyRecord.X div MyRecord.Y;
  end;
 
var
  MyRecord : TMyRecord;
  Result : Integer;
 
begin
  Writeln('Podaj pierwszą liczbę');
  Readln(MyRecord.X);
 
  Writeln('Podaj drugą liczbę');
  Readln(MyRecord.Y);
 
  Result := Dzielenie(MyRecord);
 
  Writeln('Rezultat dzielenia');
  Writeln(Result);
  Readln;
end.

Na samym początku tego programu zadeklarowano nowy typ ? TMyRecord, który jest rekordem. Teraz, żeby takiego rekordu użyć, należy zadeklarować zmienną, która wskazuje na ten typ.

Dalsza część programu powinna być oczywista ? pobieramy tutaj dwie wartości od użytkownika i przypisujemy je do elementów rekordów, tak jak robimy to ze zwykłą zmienną. Następnie cały rekord przekazujemy do funkcji, która dokonuje dzielenia.

Deklarowanie rekordu jako zmiennej

Nie jest konieczne tworzenie nowego typu dla rekordu. Oznacza to, że zamiast deklarować kolejny rekord jako nowy typ (Type), można zadeklarować go jako zmienną:

var
  Rec : record
    X, Y : Integer;
  end;

Wówczas nie jest też konieczne tworzenie nowej zmiennej ? od razu można zabrać się za przypisywanie danych do elementów rekordu.

Metody w rekordach

Delphi 8 wprowadza pewne innowacje w zapisie rekordów. Dotychczas rekord mógł zawierać jedynie Pola (ang. fields), czyli zmienne rekordowe. Teraz jest możliwe także dodawanie metod, co bardziej upodobnia rekordy do klas. Oczywiście, rekordy są prostszą strukturą niż klasy i nie mogą zwierać metod wirtualnych czy dynamicznych. Nie można dziedziczyć rekordów oraz przedefiniowywać metod.

Metody w rekordach deklaruje się identycznie jak w klasach:

type
  TRecord = record
    X, Y : Integer;
    procedure Main;
  end;

Należy zwrócić uwagę, że jawne wywołanie konstruktora w rekordzie nie jest możliwe. Oczywiście, istnieje możliwość jego deklaracji, ale jego wywołanie następuje automatycznie w momencie skorzystania z metody w rekordzie.

Deklaracja konstruktora musi nastąpić z użyciem słowa kluczowego Class, tak jak poniżej:

type
  TRecord = record
    X, Y : Integer;
    procedure Main;
    class constructor Create;
  end;
W razie zaniechania użycia słowa kluczowego Class, Delphi wyświetli komunikat o błędzie: [Error] Uni1.pas(110): Parameterless constructors not allowed on record types.

Należy również pamiętać o specyficznej budowie nagłówka metody, tak jak w przypadku klas, czyli:
procedure/function Klasa.Nazwa [parametry]

Spójrzmy na poniższy fragment kodu:

procedure TWinForm2.Button1_Click(sender: System.Object; e: System.EventArgs);
var
  R : TRecord;
begin
  R.X := 57; // przydzielenie wartości
  R.Main; // wywołanie metody
end;
 
{ TRecord }
 
class constructor TRecord.Create;
begin
  MessageBox.Show('Rozpoczynam używanie rekordu TRecord...');
end;
 
procedure TRecord.Main;
begin
  MessageBox.Show('Mój wiek: ' + Convert.ToString(X));
end;

Powyższy przykład jest oczywiście niezbyt praktyczny i użyteczny, ale pozwala na zaprezentowanie działania rekordów i wywoływania konstruktora. Można wkleić taki kod do swojego programu i zaobserwować jego działanie.

Po naciśnięciu przycisku najpierw w okienku informacyjnym pojawi się tekst: Rozpoczynam używanie rekordu TRecord..., a dopiero później: Mój wiek: 57.

W rekordach nie można używać destruktora. Przy próbie jego wykorzystania Delphi wyświetli komunikat o błędzie: [Error] Uni1.pas(111): PROCEDURE, FUNCTION, PROPERTY, or VAR expected lub [Error] Uni1.pas(111): Unsupported language feature: 'destructor'.

Metody deklarowane w rekordach są domeną języka Delphi dla .NET ? kompilator Delphi dla Win32 nie dopuści do kompilacji takiego kodu.

Zobacz też:

1 komentarz

Nie będę się wcinał w dzieło mistrza dorzucę to tylko w komentarzu.

Istnieje możliwość deklarowania tablic w rekordach, wygląda to następująco:

type //Deklaracja rekordu z 2 tablicami 16 elementowymi
TDane = record
X : array[1..16] of integer;
Y : array[1..16] of integer;
end;

var
Dane : TDane; //rzutowanie
Begin
Dane.X[1]:=10; //przykład odwołania
End;