Когда следует использовать расширенные типы записей в Delphi вместо классов?

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

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

Ответ 1

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

Записи доступны с турбо-паскалем 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, если я прав. Затем они предоставили путь для OO с паскалем. Они более или менее устарели с введением 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   |    -    |
------------------|-----------------------------|

Ответ 2

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

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

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

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

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

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

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

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

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

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

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

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

Ответ 3

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

Подробнее см. http://hallvards.blogspot.com/2007/10/more-fun-with-enumerators.html.

Ответ 4

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