В чем разница между конструктором и процедурой в записях Delphi?

Есть ли разница в поведении между вызовом конструктора и вызовом процедуры в записях Delphi? У меня есть образец кода D2010, который я хочу преобразовать в D2009 (который я использую). В примере используется конструктор без параметров, что не разрешено в Delphi 2009. Если я заменю вызов простой процедуры без параметров, есть ли какие-либо функциональные различия для записей?

I.E.

  TVector = record
  private
    FImpl: IVector;
  public
    constructor  Create;    // not allowed in D2009
  end;

становится

  TVector = record
  private
    FImpl: IVector;
  public
    procedure  Create;    // so change to procedure
  end;

Насколько я понимаю, это должно сработать, но, возможно, мне что-то не хватает.


person HMcG    schedule 22.03.2010    source источник
comment
Для меня это не похоже на объявление записи, а скорее на объявление объекта. У записей нет закрытых и общедоступных частей, конструкторов и методов.   -  person Larry Lustig    schedule 22.03.2010
comment
@Larry Lustig, да, записи могут иметь частную и публичную части. И конструкторы, свойства и методы. Они не могут наследовать или реализовывать интерфейсы. Но у них могут быть помощники по записи.   -  person Toon Krijthe    schedule 22.03.2010
comment
@ Ларри, ты на несколько лет отстал. Записи получили методы, спецификаторы видимости и операторы в Delphi 2006.   -  person Rob Kennedy    schedule 22.03.2010
comment
Я думаю, я являюсь. Где я могу прочитать об этом? И почему я должен предпочесть запись полному классу? Хранилище данных?   -  person Larry Lustig    schedule 22.03.2010
comment
В этом случае использовать перегрузку операторов в записях, которых нет в классах. Они также могут быть полезны для очень недолговечных объектов, поскольку они позволяют избежать накладных расходов на create / try / finally / free из-за подсчета ссылок.   -  person HMcG    schedule 22.03.2010
comment
Спасибо. Вы узнаете что-то новое каждый день - в моем случае, иногда даже два раза в день!   -  person Larry Lustig    schedule 22.03.2010
comment
@HMcG: Записи не считаются ссылками!   -  person Deltics    schedule 23.03.2010
comment
@Deltics, да, конечно, у меня плохо. Мозг почему-то застрял на интерфейсах. На самом деле я хотел сказать, что они автоматически уничтожаются, когда выходят за пределы области видимости, и любые поля с подсчетом ссылок, которые они содержат, будут управляться (и освобождаться, если других ссылок нет). Что может быть полезно для недолговечных служебных объектов, которые вы используете в одной области.   -  person HMcG    schedule 23.03.2010


Ответы (3)


Конструкторы записей - это абсолютно бессмысленный вводящий в заблуждение синтаксический сахар в собственном коде Win32. Единственная разница между конструктором записи и процедурой - это синтаксис:

TVector = record
  constructor Create;
end;

var
  vec : TVector;

begin
  vec:= TVector.Create;

и

TVector = record
  procedure Create;
end;

var
  vec : TVector;

begin
  vec.Create;

AFAIK есть разница в коде .NET (я не использую .NET)

person kludg    schedule 24.03.2010
comment
Я определенно склоняюсь к этому мнению. Похоже, что для всех практических целей функциональность одинакова - по какой-то причине я предполагал конструктор без параметров Create; будет автоматически вызываться при создании экземпляра записи, но это не так. - person HMcG; 24.03.2010
comment
@HMcG: в Delphi нет конструкторов (и деструкторов) по умолчанию. Каждый раз, когда создается экземпляр объекта, конструктор вызывается явно в коде (хотя сам вызов может быть где-то скрыт в VCL). Что касается записей, то деструкторов записей нет вообще, а конструктор записи - не что иное, как метод записи. - person kludg; 24.03.2010
comment
Совершенно верно, но ваш примерный код не будет компилироваться. (Таким образом, существует небольшая разница между конструкторами записей и методами, как указано в моем ответе.) Попробуйте свой код, и вы получите: [Ошибка DCC] E2394 Конструкторы без параметров не разрешены для типов записей. - person Darian Miller; 24.03.2010

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

Другое очевидное различие между конструкторами записи и процедурами записи состоит в том, что в ваших конструкторах должен быть определен хотя бы один параметр. (Поскольку записи не допускают наследования, а конструктор по умолчанию не имеет параметров.)

person Darian Miller    schedule 24.03.2010
comment
Почему? Конструктор может просто устанавливать начальные значения либо полностью сам по себе, либо получать их из какого-либо глобального источника. (По общему признанию, я еще не пробовал. Мне не нужен конструктор записи.) - person Loren Pechtel; 24.03.2010
comment
В Delphi вообще нет конструктора по умолчанию (а также деструктора по умолчанию). Вы можете объявить столько различных конструкторов / десктрукторов, сколько захотите, с любыми именами и параметрами, и ни один из них не будет вызываться неявно. Что касается записи, то конструктор записи - это всего лишь метод. - person kludg; 24.03.2010
comment
Лорен - я объяснил причину, по которой я предположил, что запись не позволяет использовать конструктор без параметров. Либо в Win32 есть конструктор по умолчанию внутри, либо они готовятся к будущей совместимости ... Я не знаю. Вопрос был не в том, «почему» вопрос был в том, «в чем разница». Фактически, разница заключается в том, что у вас не может быть конструктора без параметров. Мой ответ является правильным, но я не могу подтвердить внутреннюю работу «почему». Все, что у меня есть, это ошибка E2394, которая приведет к ошибке, если вы попробуете ее с конструктором, и нет ошибки в методе = заметная разница. - person Darian Miller; 25.03.2010

Конструктор используется для создания записи. Он вызывается при первом создании записи.

Функцию можно и нужно вызывать по мере необходимости.

Вы можете создать «конструирующую» процедуру, но вы должны вызвать ее самостоятельно.

TVector = record
private
  FImpl: IVector;
public
  procedure Create;
end;



var
  vec : TVector;
begin
  vec.Create;

Альтернативой является создание фабричной функции, возвращающей инициализированную запись.

function CreateVector(): TVector;
begin
  Result.Create;
end;
person Toon Krijthe    schedule 22.03.2010
comment
Насколько я мог судить при тестировании в D2009, конструктор Create по-прежнему нужно вызывать специально, он не вызывается автоматически. Я ожидал, что конструктор будет вызван, когда запись попадет в область видимости, но не мог заставить его это сделать. Произойдет ли это в D2010? - person HMcG; 22.03.2010
comment
Нет, конструкторы записей не вызываются автоматически. Могут быть разные конструкторы для разных целей, поэтому какой из них должен вызываться автоматически? Допустимый вызов может выглядеть так: aVector: = TVector.Create; - person Uwe Raabe; 23.03.2010
comment
Итак, учитывая, что вам нужно вызывать конструктор специально, а записи не поддерживают наследование, а записи создаются автоматически и, следовательно, не нуждаются в конструкторе, если есть какое-либо практическое различие между конструкторами Create; и процедура Create; ? - person HMcG; 23.03.2010