Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Конструкторы и деструкторы

Составляющие класса

1. Поля. Полями называются инкапсулированные в классе данные. Поля могут быть любого типа, в том числе классами.

Type

TMyClass=class

aIntField:integer;

aStrField:String;

aObjectField:TObject;

end;

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

Var

aObject:TMyClass;

begin

aObject.aIntField:=0;

aObject.aStrField:=’Строка символов’;

end;

Класс-потомок получает все поля всех своих предков и может дополнять их своими, но он не может переопределить их или удалить. Таком образом, чем ниже в дереве иерархии располагается класс, тем больше данных получают в свое распоряжение его объекты.

 

Объектами называют отдельные экземпляры классов.

Чтобы перейти от описания классов к объектам, следует выполнить объявление в секции var.

Type

TDiskGauge=class

End;

Var

DiskGauge:TdiskGauge;

 

2. Методы. Инкапсулированные в классе процедуры и функции называются методами. Они объявляются также, как и обычные подпрограммы:

Type

TMyClass=class

Function MyFunc(aPar:Integer):Integer;

Procedure MyProc;

End;

Доступ к методам класса, как и к его полям, возможен с помощью составных имен:

Var

AObject:TMyClass;

Begin

AObject.MyProc;

End;

Методы класса могут перекрываться в потомках.

Type

TparentClass=class

Procedure DoWork;

End;

TchildClass=class(TparentClass)

Procedure DoWork;

End;

Потомки обоих классов могут выполнять сходную по названию процедуру DoWork, но, в общем случае, будут делать это по-разному. Такое замещение методов называется статическим, т.к. реализуется компилятором.

В Object Pascal гораздо чаще используется динамическое замещение методов на этапе прогонки программы. Для реализации этого метод, замещаемый в родительском классе, должен объявляться как динамический (с директовой dynamic) или виртуальный (virtual). Встретив такое объявление, компилятор создаст две таблицы – DMT (Dynamic Method Table) и VMT (Virtual Method Table) и поместит в них адреса точек входа соответственно динамических и виртуальных методов. При каждом обращении к замещаемому методу компилятор вставляет код, позволяющий извлечь адрес точки входа в подпрограмму из той или иной таблицы. В классе-потомке замещающий метод объявляется с директивой override (перекрыть). Получив это указание, компилятор создаст код, который на этапе прогона программы поместит в родительскую таблицу точку входа метода класса-потомка, что позволит родителю выполнить нужное действие с помощью нового метода.

Разница между динамическими и виртуальными методами состоит в том, что таблица динамических методов DMT содержит адреса только тех методов, которые объявлены как dynamic в данном классе, в то время как таблица VMT содержит адреса всех виртуальных методов не только данного класса, но и всех его родителей. Значительно большая по размеру таблица VMT обеспечивает более быстрый поиск, в то время как при обращении к динамическому методу программа сначала просматривает таблицу DMT у объекта, затем – у его родительского класса и так далее, пока не будет найдена нужная точка входа.

Динамически перекрываемые методы часто могут вообще ничего не делать. Такие методы называются абстрактными, они обязаны перекрываться в потомках. Программист может запретить вызов абстрактного метода, объявив его с директивой abstract. В грамотно составленной программе абстрактные методы никогда не вызываются. Классы, содержащие абстрактные методы, называются абстрактными. Такие классы инкапсулируют общие свойства своих неабстрактных потомков, но объекты абстрактных классов никогда не создаются и не используются. Для эксплуатации абстрактных классов в библиотеку классов Delphi включаются классы-потомки, в которых перекрываются абстрактные методы родителя.

 

Конструкторы и деструкторы

В состав любого класса входят два специальных метода – конструктор и деструктор. У класса Tobject эти методы называются Create и Destroy, так же они называются и в подавляющем большинстве потомков. Конструктор распределяет объект в динамической памяти и помещает адрес этой памяти в переменную Self, которая автоматически объявляется в классе. Деструктор удаляет объект из кучи. Обращение к деструктору должно предварять любое обращение к полям и некоторым методам объекта. По своей форме конструкторы и деструкторы являются процедурами, но объявляются с помощью зарезервированных слов Constructor и Destructor:

Type

TMyClass=class

IntField:Integer;

Constructor Create(Value:Integer);

Destructor Destroy;

End;

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

Var

MyObject:MyClass;

Begin

MyObject:=TmyClass.Create;

MyObject.Free;

End;

В базовом классе TObject определен метод Free, который сначала проверяет действительность адреса объекта и лишь затем вызывает деструктор Destroy.

Большинство конструкторов реализуют некоторые действия, необходимые для правильной работы объекта. Поэтому в конструкторе класса-потомка следует сначала вызвать конструктор своего родителя, а уже затем осуществлять дополнительные действия. Вызов любого метода родительского класса достигается с помощью зарезервированного слова Inherited (унаследованный):

Constructor TmyClass.Create(Value:Integer);

Begin

Inherited Create; // вызываем унаследованный конструтор

End;

Некоторые методы могут вызываться без создания и инициации объекта. Такие методы называются методами класса, они объявляются с помощью зарезервированного слова class:

Type

TMyClass=class

Class Function GetClassName:String;

End;

Var

S:String;

Begin

S:=TMyClass.GetClassName;

End;

Методы класса не должны обращаться к полям, т.к. в общем случае вызываются без создания объекта, а следовательно, в момент вызова полей просто не существует. Обычно они возвращают служебную информацию о классе – имя класса, имя его родительского класса, адрес метода и т.п.

Конструктор применяется к классу и к объекту. Если конструктор применяется к классу,

DiskGauge:=TdiskGauge.Create;

то выполняется следующая последовательность действий:

· в динамической памяти выделяется место для нового объекта;

· выделенная память заполняется нулями;

· выполняются заданные программистом действия конструктора;

· ссылка на созданные объект возвращается в качестве значения конструктора; тип возвращаемого значения совпадает с типом класса, использованного при вызове.

Если конструктор применяется к объекту

DiskGause.Create;

то новый объект не создается, а происходит переинициализация полей существующего. В этом случае конструктор не возвращает никакого значения.

Деструктор уничтожает объект, к которому применяется, в результате:

· выполняется заданный программистом код деинициализации,

· освобождается занимаемая объектом динамическая память.

 

Одноименные методы

В Delphi 4,5 появилась возможность в рамках одного класса иметь несколько одноименных методов. Механизм перекрытия родительского метода одноименным методом потомка приводит к тому, что потомок «не видит» перекрытый родительский метод и может обращаться к нему лишь с помощью зарезервированного слова Inherited. В Delphi 4 введено зарезервированное слово overload (перезагрузить), с помощью которого становятся видны одноименные методы как родителя, так и потомка. Чтобы одноименные методы можно было отличить друг от друга, каждый из них должен иметь уникальный набор параметров. При обнаружении одноименного метода компилятор предупреждает о том, что у класса уже есть аналогичный метод с другими параметрами. Для подавления сообщений объявление одноименного метода можно сопровождать зарезервированным словом reintroduce (вновь ввести).

Пример: В классе Tform1 используется 4 одноименных метода Close. Лишь один из них – унаследованный метод без параметра выполняет свои основные функции – закрывает окно. Три других отличаются набором параметров и выводят сообщения в заголовок окна.

Procedure TForm1.Button1Click(Senter:TObject);

Begin

Close(‘Строка символов’);

End;

Procedure TForm1.Button2Click(Senter:TObject);

Begin

Close(123);

End;

Procedure TForm1.Button3Click(Senter:TObject);

Begin

Close(20,300);

End;

Procedure TForm1.Button4Click(Senter:TObject);

Begin

Close;

End;

В разделе private класса Tform1 вставить 3 объявления методов Close

Private

Procedure Close(S:string); reintroduce; overload;

Procedure Close(I:integer); reintroduce; overload;

Procedure Close(I,J:integer); reintroduce; overload;

Implementation

Procedure Tform1.Close(S:String);

Begin

Caption:=S;

End;

Procedure Tform1.Close(I:Integer);

Begin

Caption:=IntToStr(I);

End;

Procedure Tform1.Close(I,J:Integer);

Begin

Caption:=IntToStr(I*J);

End;

3. Свойства. Свойства – это специальный механизм классов, регулирующий доступ к полям. Свойства объявляются с помощью зарезервированных слов property, read и write (слова read и write считаются зарезервированными только в контексте объявления свойства). Обычно свойство связано с некоторым полем и указывает те методы класса, которые должны использоваться при записи в это поле или при чтении из него.

Type

TClass=class

IntField:integer;

Function GetField:Integer;

Procedure setField(value:Integer);

Property IntegerValue:Integer read GetField write SetField;

 

В контексте программы свойство ведет себя как обычное поле.

Var

aClass:TClass;

value:Integer;

begin

aClass:=TClass.Create; {Обязательно! Перед обращением к полю или свойству!}

aClass.IntegerValue:=0;

Value:=aClass.IntegerValue;

End;

Разница между оператором

aClass.IntField:=NewValue;

и оператором

aClass.IntegerValue:=NewValue;

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

Если необходимо, чтобы поле было доступно только для чтения или только для записи, следует опустить часть write или read. Вообще говоря, свойство сожжет и не связываться с полем. Фактически оно описывает один или два метода, которые осуществляют некоторые действия над данными того же типа, что и свойство.

 

ОБЪЯВЛЕНИЕ КЛАССА

 

Любой вновь создаваемый класс может содержать секции (разделы), определяемые зарезервированными словами

· published (декларированные),

· private (личные),

· protected (защищенные),

· public (доступные),

· automated (автоматизированные).

Внутри каждой секции вначале определяются поля, а затем – методы и свойства.

Секции определяют область видимости элементов описания класса. Секция public не накладывает ограничений на область видимости перечисляемых в ней полей, методов и свойств – их можно вызывать в любом другом модуле программы. Секция published также не ограничивает область видимости, однако в ней перечисляются свойства, которые должны быть доступны не только на этапе исполнения, но и на этапе конструирования объектов. Секция published используется только при разработке нестандартных компонентов. Среда Delphi помещает описания компонентов, вставленных в форму, в специальную секцию без названия, которая располагается сразу за заголовком класса и продолжается до первой объявленной секции. Это секция published. Программисту не следует помещать в нее собственные элементы описания класса или удалять из нее элементы, вставленные средой. Секция private сужает область видимости до минимума: личные элементы описания доступны только внутри методов данного класса и в подпрограммах, находящихся в том же модуле, где описан класс. Элемент, объявленный в секции private, становится недоступным даже ближайшим потомкам класса, если они размещаются в других модулях. Секция protected доступна только методам самого класса, а также любым его потомкам независимо от того, находятся ли они в том же модуле или нет. Секция automated используется только для объявления свойств и методов, которые будут добавлены к так называемому интерфейсу OLE-объектов автоматизации; область видимости членов этой секции не ограничена.

В Object Pascal разрешается сколько угодно раз объявлять любую секцию, причем порядок следования секций не имеет значения. Любая секция может быть пустой.

При объявлении класса-потомка разрешается перемещать элементы класса из одной области видимости в другую. После перемещения в секцию private элемент объявления становится невидимым потомкам (если потомок, как это обычно бывает, объявляется в другом модуле) и, следовательно, его уже нельзя переместить в другую секцию.

Класс может объявляться только в интерфейсной области модуля или в самом начале области реализации. Нельзя объявлять классы в разделе описания подпрограмм.

 

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...