Здавалка
Главная | Обратная связь

Объектно-ориентированное программирование в Турбо Паскале.

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

 

Туре

<имя класса> = Object

<имя поля данных 1> : <тип данных 1>;

<имя поля данных N> : < тип данных N>;

Procedure <имя метода 1>(<список параметров>);

Function <имя метода 2>(<список параметров>):<тип функции>;

Procedure <имя метода L>(<список параметров>);

Function <имя метода М>(<список параметров>):<тип функции>;

End;

 

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

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

 

Procedure <имя класса>.<имя метода>;

<описание локальных переменных, процедур и функций>

Begin <операторы> End;

 

Function <имя класса>.<имя метода>;

<описание локальных переменных, процедур и функций>

Begin <операторы> End;

 

Обращение к полям и методам класса осуществляется с указанием имени переменной (объекта), по аналогии с обращением к полям записи с использованием:

1. составных имен:
<имя объекта>.<имя поля>
<имя объекта>.<имя метода>(<список фактических параметров>);

2. оператора присоединения with:
with <имя объекта> do
begin
...<имя поля>...
...<имя метода>(<список фактических параметров>)...
end;

 

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

Var

<имя указателя>: ^<имя класса>;

Для размещения объекта в динамической памяти используют процедуру или функцию New:

New (<имя указателя>);

<имя yкaзaтeля>:=New(<тип «указатель на класс»>).

Если динамический объект использует виртуальные методы класса, то до обращения к этим методам он должен вызвать конструктор:

<имя указателя>^.<имя конструктора>(<список параметров>).

В ТП имеется возможность использования расширенного варианта процедуры и функции New, который позволяет в одной операции выделить память под объект и вызвать конструктор:

New(<имя указателя>,<имя конструктора>(<список параметров>));

<имя указателя>:=New(<Tип «указатель на класс»>,
<имя конструктора>(<список параметров>))

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

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

Dispose(<имя указателя>);

Если класс объекта включает виртуальные методы, то при уничтожении объекта обязательно должен вызываться специальный метод деструктор. Служебное слово Destructor, что подразумевает выполнение некоторых специальных действий при уничтожении объекта: деструктор определяет реальный размер объекта и передает его процедуре Dispose.

Конструктор рекомендуется называть Init, деструктор обычно называют Done.

Деструктор можно вызвать в расширенном формате процедуры Dispose:

Dispose (<имя указателя>,<имя деструктора>);

 

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

<объект класса-родителя> := <объект класса-потомка>

 

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

1. инициализировать поля в основной программе операторами присваивания вида:
<имя объекта>.<имя поля> := <значение>

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

3. использовать типизированные константы вида:
Const
<имя объекта> : <имя класса> =(<имя поля 1> : <значение поля 1>;
<имя поля 2> : <значение поля 2>;
<имя поля К>:<значение поля К>);
Const
Vl :Win = (Xl:20; Yl:5; X2:40; Y2:15);

Параметр Self является обобщенным именем экземпляра класса, которое неявно используется внутри методов для обращения к полям и методам.

Туре

Rec = Record {тип записи}

X, Y: word; {поля данных записи}

end;

Pas = Object {объявление класса}

X, У: word; {поля данных класса}

Procedure Init(P: Rec); {метод класса}

end;

Procedure Pos.Init;

Begin

with Р do {присоединить имя записи Р}

begin

Self.X: = X; SelfY:=Y;

end

End;

 

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

Доступ к полям, описанным в классе-родителе, осуществляется также как к собственным. Поиск метода в иерархии классов выполняется следующим образом:

1. В первую очередь компилятор устанавливает тип объекта.

2. Далее он ищет метод в классе объекта и если находит, то подключает его.

3. Если метод в классе объекта не найден, то идет поиск в классе-родителе. В случае успеха вызывается метод родителя.

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

Если компилятор не обнаруживает метод, то он фиксирует ошибку компиляции.

 

Структура описания класса-потомка:

Туре <имя класса-потомка> = Оbject(<имя класса-родителя>)

<новые поля класса-потомка>

<новые методы класса-потомка>

End;

 

ТП реализует механизмы простого и сложного полиморфизма:

1. Простой полиморфизм обеспечивает возможность задания различных реализаций некоторого единого по названию метода для классов различных уровней иерархии. Одноименные методы в этом случае называют статическими полиморфными. Конкретный метод определяется типом объекта на этапе компиляции программы (раннее связывание).

2. При сложном полиморфизме конкретный метод определяется типом объекта, на этапе выполнения программы (позднее связывание). Необходимость позднего связывания обусловлена тем, что в ТП разрешается объекту класса-родителя присваивать объект класса-потомка. Поскольку при передаче объектов в качестве параметров используются указатели, формально описанному параметру типа некоторого класса может соответствовать фактический параметр не только того же типа, но и типа класса, производного от указанного. В тех случаях, когда реальный тип объекта не определен, связывание объекта и метода на этапе компиляции программы приводит к тому, что при любых условиях вызывается родительский метод. Применение позднего связывания позволяет правильно определить требуемый метод. Полиморфные методы, для которых применяется позднее связывание, называют виртуальными. Для описания виртуальных методов используется служебное слово virtual.

При использовании виртуальных методов должны выполняться следующие правила:

1. Если в некотором классе метод описан как виртуальный, то все производные классы, включающие метод с тем же именем, должны описать этот метод как виртуальный. Нельзя заменить виртуальный метод статическим.

2. Порядок расположения, количество и типы формальных параметров в одноименных виртуальных методах должны оставаться неизменными.

3. Класс, содержащий виртуальные методы, должен включать специальный статический метод - конструктор. Обозначается специальным словом Constructor. Конструктор неявно выполняет настройку механизма позднего связывания (обеспечивает связь объекта с ТВМ). Этот метод должен быть вызван до первого обращения к виртуальному методу.

Тип полиморфного объекта в программе можно определить с помощью функции TypeOF:

TypeOF(<имя объекта>): Pointer ;

TypeOF(<имя класса>): Pointer ;

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

if TypeOF(Self) = ТуреОF(<ИмяЭкземпляра>) then ...;

 

 





©2015 arhivinfo.ru Все права принадлежат авторам размещенных материалов.