9 Билет
Объекты могут размещаться в динамической памяти и ими можно манипулировать с помощью указателей, как и с тесно связанными с ними типами записей, что всегда имело место в Паскале. Турбо Паскаль включает несколько мощных расширений для выполнения динамического размещения и удаления объектов более легкими и более эффективными способами.
Объекты могут размещаться, как области памяти, на которые ссылается указатель, с помощью процедуры New:
var
CurrentPay: Real;
P: ^TSalaried;
New(P);
Как и для типов записей, процедура New выделяет в динамической памяти пространство, достаточное для размещения реализации указателя базового типа и возвращает адрес этого пространства в указателе.
Если динамический объект содержит виртуальные методы, то он должен инициализироваться с помощью вызова конструктора перед тем, как будет вызван любой из его методов:
P^.Init("Sara Adams", "Account manager", 2400);
Затем вызовы методов могут происходить в обычном порядке, с использованием имени указателя и ссылочного символа вместо имени реализации, которое использовалось бы при обращении к статически размещенному объекту:
CurrentPay := P^.GetPayAmount;
Особой разновидностью методов являются конструкторы и деструкторы. Создание объекта включает выделение памяти под экземпляр и инициализацию его полей, а разрушение - очистку полей и освобождение памяти. Действия по инициализации и очистке полей специфичны для каждого конкретного класса объектов. По этой причине язык Delphi позволяет переопределить стандартный конструктор Create и стандартный деструктор Destroy для выполнения любых полезных действий. Можно даже определить несколько конструкторов и деструкторов (имена им назначает сам программист), чтобы обеспечить различные процедуры создания и разрушения объектов.
Объявление конструкторов и деструкторов похоже на объявление обычных методов с той лишь разницей, что вместо зарезервированных слов function и procedure используются слова constructor и destructor. Пример:
type TPeople = class
Name: string;
Family: string;
procedure GetName;
procedure GetFamily;
construcor Create;
destrucot Destroy;
end;
Возможная реализация:
procedure TPeople.Create;
begin
TPeople.Name := ' ';
TPeople.Family := ' ';
end;
procedure TPeople.Destroy;
begin
//Пока ничего не делаем
end;
Если объект содержит встроенные объекты или другие динамические данные, то конструктор - это как раз то место, где их нужно создавать. Конструктор применяется к классу или к объекту. Конструктор создаёт новый объект только в том случае, если перед его именем указано имя класса. Если указать имя уже существующего объекта, он поведёт себя по-другому: не создаст новый объект, а только выполнит код, содержащийся в теле конструктора. Если он применяется к классу,
People := TPeople.Create;
то выполняется следующая последовательность действий:
1. В динамической памяти выделяется место для нового объекта.
2. Выделенная память заполняется нулями. В результате все числовые поля и поля порядкового типа приобретают нулевые значения, строковые поля становятся пустыми, а поля, содержащие указатели и объекты получают значение nil.
3. Затем выполняются заданные программистом действия конструктора.
4. Ссылка на созданный объект возвращается в качестве значения конструктора. Тип возвращаемого значения совпадает с типом класса, использованного при вызове (в нашем примере это тип TPeople).
Таким образом, хотя на первый взгляд синтаксис конструктора схож с вызовом процедуры (не определено возвращаемое значение), но на самом деле конструктор - это функция, возвращающая созданный и инициализированный объект. Если конструктор применяется к объекту,
People.Create;
то конструктор выполняется как обычный метод. Другими словами, новый объект не создаётся, а происходит повторная инициализация полей существующего объекта. В этом случае конструктор не возвращает никакого значения. Далеко не все объекты корректно себя ведут при повторной инициализации, поскольку программисты редко закладывают такую возможность в свои классы. Поэтому на практике повторная инициализация применяется крайне редко.
Деструктор уничтожает объект к которому применяется:
People.Destroy;
В результате выполняются:
1. Заданный программистом код завершения.
2. Освобождается занимаемая объектом динамическая память.
В теле деструктора обычно должны уничтожаться встроенные объекты и динамические данные, как правило, созданные конструктором. Как и обычные методы, деструктор может иметь параметры, но эта возможность используется крайне редко.