Как определить неявные операторы преобразования для взаимозависимых записей?

Я использую перегрузку оператора для записей в Delphi 2006. (Пожалуйста, не отвечайте на этот вопрос, сообщив мне не делать этого.)

У меня есть два типа записей, при которых неявный оператор перегружен. Они оба находятся только в реализации модуля, а не через интерфейс.

Моя проблема в том, что теперь они взаимозависимы, я не знаю, как переслать объявление второго типа в компилятор. Я знаю, как это делать с функциями, процедурами и классами, но не с записями.

Вот упрощенный пример того, что я пытаюсь сделать:

implementation

type
  TMyRec1 = record
    Field1 : Integer;
    class operator Implicit(a: TMyRec2): TMyRec1;  // <---- Undeclared Identifier here.
  end;

  TMyRec2 = record
    Field2: Integer;
    class operator Implicit(a: TMyRec1): TMyRec2;
  end;

class operator TMyRec1.Implicit(a:TMyRec2): TMyRec1;
begin
  Result.Field1 := a.Field2;
end;

class operator TMyRec2.Implicit(a:TMyRec2): TMyRec2;
begin
  Result.Field2 := a.Field1;
end;

Ответы

Ответ 1

У вас не может быть передовых объявлений для типов записей. Определите оба оператора Implicit во втором типе:

type
  TMyRec1 = record
    Field1 : Integer;
  end;

  TMyRec2 = record
    Field2: Integer;
    class operator Implicit(a: TMyRec2): TMyRec1;
    class operator Implicit(a: TMyRec1): TMyRec2;
  end;

Цитата из справка:

Неявные преобразования должны предоставляться только там, где это абсолютно необходимо, и рефлексивность следует избегать. Лучше всего позволить типу B неявно преобразовать себя в тип A, и пусть тип A не знает тип B (или наоборот).

Ответ 2

Возможно, вы сможете сделать это с помощью помощников записи.

Ниже приведено то, что я недавно сделал, чтобы обойти невозможность записи декларации forward record.

Он использует конструкцию record helper, которая, подобно implicit type casts, также имеет недостатки.
Наиболее важным является то, что будет применяться только ближайший record helper для конкретного типа record.

type
  TIpv4Address = record
  strict private
    FAddress: TIpv4Quad;
    FMask: TIpv4Quad;
  private
    class function CreateInternal(const IP_ADDR_STRING: _IP_ADDR_STRING): TIpv4Address; static;
  public
    class function Create(const IP_ADDR_STRING: _IP_ADDR_STRING): TIpv4Address; static;
    class function Count(const IP_ADDR_STRING: _IP_ADDR_STRING): Integer; static;
    property Address: TIpv4Quad read FAddress;
    property Mask: TIpv4Quad read FMask;
  end;

  TIpv4AddressList = array of TIpv4Address;

  TIpv4AddressHelper = record helper for TIpv4Address
    class function CreateList(const IP_ADDR_STRING: _IP_ADDR_STRING): TIpv4AddressList; static;
  end;

Вы используете его следующим образом:

function TAdapterInfo.GetIpAddressList: TIpv4AddressList;
begin
  Result := TIpv4Address.CreateList(AdapterInfos.IP_ADAPTER_INFO[Index].IpAddressList);
end;

- Йерун