Когда я должен использовать расширенные типы записей в Delphi вместо классов? - PullRequest
15 голосов
/ 09 мая 2009

Delphi 2006 представил новые возможности для записей, сделав их более «объектно-ориентированными».

В каких ситуациях тип записи больше подходит для дизайна, чем тип класса? Какое преимущество имеет использование этих типов записей?

Ответы [ 4 ]

15 голосов
/ 09 мая 2009

У вас есть записи, объекты и классы.

Записи доступны начиная с Turbo Pascal 1. Они легкие, могут иметь свойства и методы, но не поддерживают наследование. Есть некоторые проблемы с функциями, которые возвращают записи. Если у этих записей есть методы, это иногда выдает внутренние ошибки:

type
  TRec = record 
    function Method1: Integer;
  end;

function Func: TRec;


procedure Test;
var
  x : TRec;

begin
  Func.Method1; // Sometimes crashes the compiler
  // Circumvention:
  x := Func;
  x.Method1; // Works
end;

Объекты вводятся с Turbo Pascal 5, если я прав. Затем они предоставили путь для ОО с паскалем. Они более или менее устарели с появлением Delphi, но вы все равно можете их использовать. Объекты могут реализовывать интерфейсы.

Классы представлены в Delphi 1 и наиболее универсальны. Они реализуют интерфейсы и поддерживают наследование. Но каждая переменная класса является скрытым указателем. Это означает, что классы должны быть созданы в куче. К счастью, этот процесс в основном скрыт.

Ниже приведена таблица с различиями между ними. Я добавил интерфейс для завершения.

                  |Class|Object|Record|Interface|
------------------|-----------------------------|
Are pointers?     |  y  |  n   |  n   |    y    |
Inheritance       |  y  |  y   |  n   |    y    |
Helpers           |  y  |  n   |  y   |    n    |
Impl. Interface   |  y  |  y   |  n   |    -    |
Visibility        |  y  |  y   |  n   |    n    |
Method            |  y  |  y   |  y   |    y    |
Fields            |  y  |  y   |  y   |    n    | 
Properties        |  y  |  y   |  y   |    y    |
Consts            |  y  |  y   |  y   |    n    |
Types             |  y  |  y   |  y   |    n    |
Variants          |  n  |  n   |  y   |    n    |
Virtual           |  y  |  n   |  y   |    -    |
------------------|-----------------------------|
8 голосов
/ 09 мая 2009

Я думаю, что эти функции были также доступны в Delphi 8 и 2005.

Основная рекомендация: если у вас есть сомнения, используйте класс.

В остальном вы должны понимать главное отличие: объекты класса всегда используются через ссылку и создаются путем вызова конструктора.

Управление памятью и ее распределение для записей такое же, как и для базовых типов (т. Е. Целое, двойное). Это означает, что они передаются в методы по значению (если только не используется var). Также вам не нужно освобождать записи, и именно поэтому они поддерживают перегрузку операторов. Но нет наследования, виртуальных методов и т. Д. Новые записи могут иметь конструктор, но его использование является необязательным.

Основные области и критерии использования записей:

  • при работе со структурами из Win32 API

  • когда типы не имеют идентичности (потому что присвоение означает копирование)

  • когда экземпляры не слишком велики (копирование больших записей становится дорогим)

  • при построении типов значений, поведение которых должно имитировать числовые типы. Примерами являются DateTime, Complex Numbers, Vector и т. Д. А затем перегрузка операторов - хорошая функция, но не делайте этого решающим фактором.

И с точки зрения эффективности, не переусердствуйте:

  • для небольших типов, которые вы часто помещаете в массивы.

И, наконец, правила использования класса или записей на самом деле не изменились по сравнению с более ранними версиями Delphi.

6 голосов
/ 09 мая 2009

В дополнение к другим ответам (перегрузка операторов, облегченные типы значений), хорошей идеей будет сделать записи вашего перечислителя вместо классов. Поскольку они размещены в стеке, нет необходимости создавать и уничтожать их, что также устраняет необходимость в скрытом блоке try..finally, который компилятор размещает вокруг перечислителей класса.

См. http://hallvards.blogspot.com/2007/10/more-fun-with-enumerators.html для получения дополнительной информации.

1 голос
/ 09 мая 2009

Вы можете использовать оператор перегрузки (например, неявные преобразования). Это можно делать и в Delphi 2007+ или 2006.NET для объектов, но только для этих записей в win32 2006 года.

...