Дельфи:Конструктор записи и фабричная функция

StackOverflow https://stackoverflow.com/questions/1116709

  •  12-09-2019
  •  | 
  •  

Вопрос

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

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

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;

Я чувствую, что конструкторы более инкапсулированы, но из-за них легко запутаться при чтении кода.Это делает его похожим на класс, в котором отсутствует вызов free.Это еще и печатать...

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

Это было полезно?

Решение

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

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

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;

Другие советы

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top