Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lektsii_po_OOP_Delphi.docx
Скачиваний:
54
Добавлен:
31.05.2015
Размер:
2.39 Mб
Скачать

Interface

type

TMyObject = class (TObject)

MyField:integer;

Function print: integer;

end;

Implementation

function TMyObject.print;

begin

writeln('Hello!!!!');

end;

end.

В примере описан класс TMyObject, имеющий поле MyField и метод print.

Классы описываются в секции интерфейса модуля.

Чтобы использовать этот новый тип(класс) надо объявить переменную этого типа, которая будет называться экземпляром класса (объектом).

var

v: TMyObject;

После этого можно вызывать методы класса: v.print;

Можно создать много экземпляров одного класса. Поля класса это данные уникальные для каждого экземпляра класса. А методы у нескольких экземпляров одного класса общие. Методы это процедуры и функции, описанные внутри класса и предназначенные для операций над полями (хотя и не обязательно)

  1. ПРИНЦИПЫ ООП

К основным принципам ООП относятся следующие: инкапсуляция, наследование и полиморфизм.

4. Инкапсуляция

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

  • Пользователь может взаимодействовать с объектом только через интерфейс.

  • Пользователь не может использовать закрытые данные и методы.

В объектах Delphi пользователь объекта может быть полностью отгорожен от полей при помощи свойств.

Свойство определяется тремя основными элементами: полем и двумя методами, которые осуществляют его чтение/запись.

В Delphi для создания скрытых полей или методов их достаточно объявить в секции private.

TMyClass = class

private

FMyField: Integer;

procedure SetMyField(const Value: Integer);

function GetMyField: Integer;

public

property MyField: Integer read GetMyField write SetMyField;

end;

Свойства используются в Delphi для создания интерфейса доступа к скрытым полям. Для описания свойства в Delphiслужит словоproperty.

Пример класса со свойством:

type

TMyClass = class

private

FMyField: Integer;

procedure SetMyField(const Value: Integer);

function GetMyField: Integer;

public

property MyField: Integer read GetMyField write SetMyField;

end;

function TMyClass.GetMyField: Integer;

begin

Result := FMyField;

end;

procedure TMyClass.SetMyField(const Value: Integer);

begin

FMyField := Value;

end;

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

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

type

TMyClass = class

property AProperty: TSomeType read getValue

end;

В этом примере значение свойства можно лишь прочитать.

Для придания свойству значения по умолчанию используется ключевое свойство default:

property Visible: Boolean read getVisible write setVisible default true;

  1. НАСЛЕ́ДОВАНИЕ — механизм объектно-ориентированного программирования, позволяющий описать новыйклассна основе уже существующего (родительского), при этом свойства и функциональность родительского класса заимствуются новым классом.

Класс, от которого произошло наследование, называетсябазовым или родительским (англ.base class). Классы, которые произошли от базового, называются потомками, наследниками или производными классами (англ.derived class).

Для использования механизма наследования в Delphiнеобходимо в объявлении класса справа от словаclass указать класс предок:

TNewObject = class (TOldObject)

Абсолютно все классывDelphiявляются потомками классаTObject. Если класс-предок не указан, то подразумевается, что новый класс является прямым потомком классаTObject.

Следующие 2 выражения одинаково верны:

TMyObject = class(TObject);

TMyObject = class;

Состав класса TObject: (некоторые важные методы)

constructor Create

Конструктор. Создает новый экземпляр объекта.

destructor Destroy; virtual;

Деструктор. Производит действия по уничтожению экземпляра объекта.

procedure Free;

Эта процедура может использоваться вместо деструктора. Проверяет передаваемы деструктору указатель на экземпляр.

class function NewInstance: TObject; virtual;

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

procedure FreeInstance; virtual;

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

class function ClassName: string;

Возвращает строку с именем класса вызвавшего объекта.

class function ClassParent: TClass;

Возвращает указатель на класс-предок.

class function InstanceSize:Word;

Возвращает размер экземпляра объекта.

Унаследованные от предка поля и методы доступны в дочернем классе, если имеет место совпадение имен методов, то говорят, что они перекрываются.

Рассмотрим поведение методов при наследовании. Методы делятся на 3 группы: статические (static), виртуальные (virtual) и динамические (dynamic).

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

Type

T1Obj = class

i : Extended;

procedure SetData(AValue : Extended );

end;

T2Obj = class(T1Obj)

i : Integer;

procedure SetData(AValue : Integer );

end;

……

procedure T1Obj.SetData;

begin

i:=v;

end;

procedure T2Obj.SetData;

begin

i:=0;

inherited SetData(0.99);

end;

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

Принципиально отличаются от статических виртуальные и динамические методы. Виртуальные и динамические методы объявляются путем добавления директивы virtual или dynamic. С точки зрения наследования методы этих двух видов одинаковы: они могут быть перекрыты в дочернем классе только одноименными методами, имеющими тот же тип.

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

Когда компилятор встречает обращение к виртуальному методу, он подставляет вместо обращения к конкретному адресу код, который обращается к специальной таблице и извлекает оттуда специальный адрес. Эта таблица называется таблицей виртуальных методов (Virtual Method Table, VMT). Такая таблица есть для каждого объектного типа. В ней хранятся адреса всех виртуальных методов класса, независимо от того, унаследованы ли они от предка или перекрыты. Таким образом, они вызываются сравнительно быстро (хотя медленнее статических), однако для хранения указателей на них требуется большое количество памяти.

Динамические методы вызываются медленнее, но позволяют более экономно расходовать память. В таблице динамических методов (Dynamic Method Table, DMT) класса хранятся адреса только тех динамических методов, которые описаны в данном классе. При вызове динамического метода, происходит поиск в этой таблице, а в случае неудачи просматриваются все классы-предки в порядке иерархии, вплоть до TObject.

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

var

v: TMyObject;

begin

v.print;

end.

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

var

v: TMyObject;

begin

v:=TMyObject.Create;

v.print;

end.

Для перекрытия и виртуальных и динамических методов служит директива override.

Пример (Рассмотрим позже в следующей главе (Полиморфизм)):

6. ПОЛИМОРФИ́ЗМ— возможность объектов с одинаковой спецификацией иметь различную реализацию.

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

Пример:

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

type

TField = class

function GetData: string; virtual; abstract;

end;

TStringField = class(TField)

Data:string;

function GetData: string; override;

end;

TIntegerField = class(TField)

Data: Integer;

function GetData: string; override;

end;

TExtendedField = class(TField)

Data: Extended;

function GetData: string; override;

end;

function TStringField.GetData;

begin

GetData:=Data;

end;

function TIntegerField.GetData;

begin

GetData:=IntToStr(Data);

end;

function TExtendedField.GetData;

begin

GetData:=FloatToStrF(Data,ffFixed,7,2);

end;

……….

procedure ShowData(Afield: TField);

begin

Form1.Label1.Caption:= Afield.GetData;

end;

Метод (функция) GetData описан как абстрактный. Абстрактными называются методы, которые определены в классе, но не содержат никаких действий, никогда не вызываются и должны быть переопределены в потомках класса. Абстрактными могут быть только виртуальные и динамические методы.

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

Правило контроля соответствия типов языка Pascal (как впрочем и пожалуй других объектно-ориентированных языков программирования) говорят, что объекту как указателю на экземпляр объектного типа может быть присвоен адрес экземпляра любого из дочерних типов. В процедуре ShowData параметр описан как TField – это значит, что в качестве параметра можно передавать объекты классов TStringField, TIntegerField, TExtendedField так и любого другого потомка класса TField.

В данном примере при вызове метода GetData объекта TField управление будет передано тому методу, который соответствует классу фактически переданного объекта. Это и есть принцип полиморфизма.

Любой метод (и статический и виртуальный) может быть перегружен с помощью ключевого слова overload. Например, можно определить в одной и той же области видимости несколько процедур или функций с одинаковыми именами, но различающихся по числу или типу параметров. Если после объявления метода поставить ключевое слово overload, то при его вызове компилятор проанализирует передаваемые параметры, их число и тип и вызовет тот метод, которые подходит данным параметрам.

Например, вы можете определить следующие функции:

function Divide(X, Y : Real); Real; overload;

begin

Result := X / Y;

end;

function Divide(X, Y: Integer): Integer; overload;

begin

Result := X div Y;

end;

Обе функции объявлены как перегруженные с именем Divide, но первая из

них получает действительные аргументы, а вторая — целые. Значит, если будет записан вызов Divide(5, 3), будет вызываться первая функция, а при вызове Divide(5.0, 3.0) — вторая.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]