Предварительное объявление записей (record) в Delphi

Вольный перевод поста Forward record declarationopen in new window.

Предварительная объявление не новая концепция. Она уже присутствовала в оригинальном Паскале Вирта, где она позволяла программистам делать только одну вещь — вызывать процедуру A из процедуры B и вызывать процедуру B из процедуры A. В те времена не было интерфейсов, классов, модулей, только процедуры и функции. Вот пример

procedure ProcA; forward;

procedure ProcB;
begin
  ProcA;
end;

procedure ProcA;
begin
  ProcB;
end;
1
2
3
4
5
6
7
8
9
10
11

Более знакомая современная концепция — предварительное объявление для классов и интерфейсов.

type
  TClassA = class;

  TClassB = class
    ObjA: TClassA;
  end;

  TClassA = class
    ObjB: TClassB;
  end;

  IIntfA = interface;

  IIntfB = interface
    function Other: IIntfA;
  end;

  IIntfA = interface
    function Other: IIntfB;
  end;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

В тоже время в Object Pascal нет концепции предварительного объявления записей. Следующий код не компилируется

type
  TRecA = record;

  TRecB = record
    function Other: TRecA;
  end;

  TRecA = record
    function Other: TRecB;
  end;
1
2
3
4
5
6
7
8
9
10

Существует трюк который позволяет достичь аналогичной функциональности с помощью другого синтаксического сахара - record helpers. Мы можем удалить объявление TRecB.Other из TRecB и потом снова добавить его через хелпер для TRecB.

type
  TRecB = record
  end;

  TRecA = record
    function Other: TRecB;
  end;

  TRecBHelper = record helper for TRecB
    function Other: TRecA;
  end;
1
2
3
4
5
6
7
8
9
10
11

Но помните, что это решение менее стабильно: другой код может скрыть функционал TRecBHelper введя свой собственный хелпер для TRecB. (противная особенность языка которая действительно должна быть исправлена уже давно)

Последниее изменение: 24.08.2023, 06:42:55