Delphi: конструктор записей и функция фабрики - PullRequest
17 голосов
/ 12 июля 2009

Так что будет предпочтительным способом инициализации записей?

с «заводской функцией»:

TMyRecord = record
  valueX: integer;
  valueY: integer;
end;

function MyRecord(const AValueX, AValueY: integer): TMyRecord;
begin
  result.valueX := AValueX;
  result.valueY := AValueY;
end;

var
  myrec: TMyRecord;
begin
  myrec := MyRecord(1, 2);
end;

или конструктор:

TMyRecord = record
  valueX: integer;
  valueY: integer;
  constructor Create(const AValueX, AValueY: integer);
end;

constructor TMyRecord.Create(const AValueX, AValueY: integer);
begin
  self.valueX := AValueX;
  self.valueY := AValueY;
end;

var
  myrec: TMyRecord;
begin
  myrec := TMyRecord.Create(1, 2);
end;

Мне кажется, что конструктор более инкапсулирован, но при чтении кода легко запутаться Это делает его похожим на класс, в котором отсутствует призыв к бесплатному. Это также больше, чтобы напечатать ...

Почему вы предпочитаете один другому?

Ответы [ 4 ]

11 голосов
/ 12 июля 2009

Я предпочитаю классы, но если мне нужно использовать записи, я хотел бы относиться к ним как можно ближе к классам. Поэтому я использую конструктор записей.

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

type 
  TMyRec = record
    ..
    procedure X;
  end;


function GetRec: TMyRec;



procedure Test;
var
  r1, r2 : TMyRec;
begin
  r1 := GetRec;
  r1.X; // internal error
  r2 := r1;
  r2.X; // No internal error;
2 голосов
/ 12 марта 2015

Я бы предпочел "фабричный метод", как

  function TMyRecord.CreateRec(const AValueX, AValueY: integer): TMyRecord;

Отдельные фабричные функции утечки инкапсуляции и конструкторы записей просто запутывают ИМХО.

1 голос
/ 13 июля 2009

В проекте Delphi, который я создал, я использовал записи вместо классов, чтобы уменьшить количество накладных расходов в списке. У меня будет несколько сотен записей в динамическом массиве, поэтому я создал две записи. Первая запись была для самого предмета. Поля были сделаны закрытыми (да, вы можете использовать личные / защищенные с записями) и добавили свойства только для чтения в открытый раздел. Также был добавлен дополнительный конструктор для правильной инициализации записи. Эта настройка позволила мне защитить содержимое этой записи от других разработчиков. Вторая запись была просто оберткой вокруг динамического массива предыдущего типа записи. Массив будет закрытым, и я добавил методы для получения, добавления и удаления записей в этом списке. В результате весь список защищен от неправильного использования другими разработчиками, а также имеет гораздо меньше накладных расходов, чем обычное решение TList / TObjectList.

Имейте в виду, что записи не являются классами. Вы не можете наследовать конструкторы и другие методы. Они имеют меньшую функциональность, чем настоящие классы в средах WIN32. В .NET их просто снова переводят в классы. И не очень полезно использовать конструктор add, когда разработчики могут легко изменять содержимое каждого поля в вашей записи. Вместо этого вы должны использовать конструкторы для защиты этих полей.

0 голосов
/ 13 июля 2009

Я обычно не создаю конструкторы для записей. Он не совместим со всеми версиями (и FPC). Более того, обычно они используются только в одном месте, и часто достаточно заполнителя.

...