
- •Основы объектно-ориентированного анализа и проектирования Введение в объектно-ориентированное программирование Эволюция разработки программного обеспечения
- •Технологии программирования
- •Основные концепции объектно-ориентированного программирования
- •Реализация объектно-ориентированного подхода Инкапсуляция. Свойства
- •При использовании динамики:
- •Конструкторы объектов
- •Деструкторы объектов
- •Наследование, агрегация
- •Полиморфизм, виртуальные и динамические методы
- •Абстрактные методы
- •Перегрузка методов
- •События и делегирование
- •Приведение объектных типов, операторы is и as
- •Области видимости
- •Перекрытие и переопределение свойств
- •Объектно-ориентированное программирование в Borland Delphi. Применение объектно-ориентированного программирования
- •Иерархия библиотечных классов в Borland Delphi.
- •Создание компонентов в среде Delphi Способы создания компонентов
- •Процесс создания компонентов
- •Создание модуля
- •Создание описания и реализации класса для компонента
- •Тестирование неустановленного компонента
- •Создание графического изображения для компонента
- •Инсталляция и деинсталляция компонента
- •Создание свойств, событий и методов компонентов Работа со свойствами
- •События
- •Обработка сообщений Windows
- •Сообщения Windows
- •Обработчики сообщений Windows
Реализация объектно-ориентированного подхода Инкапсуляция. Свойства
Имеются три принципа, составляющие суть объектно-ориентированного программирования: инкапсуляция, наследование и полиморфизм.
По определению инкапсуляция - сведение кода и данных воедино в одном объекте данных, получившем название класса. Причем, прямой доступ к данным нежелателен: чтение и обновление их содержимого должно производиться посредством вызовов соответствующих процедур и функций.
Объект рассматривается как нечто, обладающее состоянием и поведением. Состояние - это данные. Поведение - это код. Причем состояние, то есть данные могут меняться только в процессе поведения и не могут быть изменены непосредственно из внешнего мира. Таким образом, сведение кода и данных вместе и дает возможность создать нечто, являющееся объектом.
В не объектно-ориентированных языках программирования стандартным решением было бы создание структур данных и соответствующих им функций и размещение их в отдельно компилируемом исходном файле. Но такой путь не лишен недостатков. Прежде всего отсутствует явная связь между данными и кодом, следствием чего может являться то, что либо сам разработчик, либо другой программист имеют возможности непосредственного доступа к данным, минуя связанные с ними функции. Это может привести к проблемам, связанным с тем что в процессе разработки структуры данных могут меняться.
В объектно-ориентированных языках программирования имеется особая структура, которая называется классом. В Object Pascal классом называется такая структура, которая может иметь в своем составе поля, методы и свойства. Определенный таким образом тип данных также называют объектным типом:
type
TMyObject = class (TObject)
MyField: integer;
Function MyMethod: integer;
End;
Переменные типа класс называют экземплярами класса или объектами. Из чего состоит объект? Поля объекта аналогичны полям записи. Это - данные, уникальные для каждого созданного в программе экземпляра класса. Описанный здесь класс TMyObject имеет одно поле - MyField. В отличие от полей, методы у двух объектов одного класса общие. Методы - это процедуры или функции, описанные класса и предназначенные для операций над его полями. В состав класса входит указатель на таблицу, где содержится вся информация, нужная для вызова методов. От обычных процедур и методы отличаются тем, что им при вызове передается указатель на тот объект, который их вызвал. Поэтому обрабатываться будут поля именно того объекта, который вызвал метод. Внутри метода указатель на вызвавший его объект доступен под зарезервированным именем Self. Для описания реализации методов класса используется следующая запись:
Function TMyObject.MyMethod;
begin
. . .
end;
Понятие свойства будет рассмотрено далее. Пока можно определить его как поле, доступное для чтения и записи не напрямую, а через соответствующие методы. Рассмотрим пример:
TSimpleObject = class
Fx, Fy : integer;
Procedure SetXY(x,y : integer);
Procedure GetXY(var x,y : integer);
End;
Procedure TSimpleObject.SetXY(x,y : integer); {- также неявно передается указатель Self )
Begin
Fx := x; {указатель Self перед Fx опущен, но подразумевается}
Self.Fy := y; {указатель Self перед Fy есть, но мог бы быть опущен}
End;
Procedure TSimpleObject.GetXY(var x,y : integer);
Begin
. . .
End;
Var
01, 02, 03: TSimpleObject; {создаем три объекта – то есть набора полей}
xl,yl: integer;
Begin
. . .
01.SetXY(10,20) ; {устанавливаем значения полей первого объекта}
02.SetXY(ll,22) ; { устанавливаем значения полей второго объекта }
03.SetXY (-10, 0) ; { устанавливаем значения полей третьего объекта }
02.GetXY(xl,yl); {xl,yl примут значения 11,22, т.к. работаем с объектом 02}
End;
Как видно из примера, указатель Self явно используется крайне редко, хотя и постоянно подразумевается.
Классы могут быть описаны либо в секции интерфейса модуля, либо на верхнем уровне вложенности секции реализации. Не допускается описания классов внутри процедур и других блоков кода.
Разрешено опережающее объявление классов, как в следующем пример
Type
TFirstObject = class;
TSecondObject = class (TOsject);
First: TFirstOsject;
. . .
end;
TFirstObject = class (TObject)
. . .
end;
Чтобы использовать новый тип в программе, нужно, как минимум, объявить переменную этого типа, которая как уже было сказано называется экземпляром класса или объектом:
Var
AMyObject: TMyObject;
Вызов методов класса и доступ к его полям осуществляется аналогично доступу к полям записи. Например:
AMyObject.Field:=10;
Writeln(AMyObject.MyMethod);
Между терминами класс и объект существует четка граница: класс - это описание, объект - то, что создано в соответствии с этим описанием.
Рассмотрим следующий пример: стек, который является широко распространенным в программировании объектом. Стек, как известно можно организовать либо на основе динамического списка, либо путем использования статического или динамического массива. Но, в любом случае операции над данными будут те же. А именно: добавить элемент в стек, прочитать элемент из стека, если он не пуст. Эти две операции будут методами класса.
TObStack= class(TObject)
procedure InStack(Elem:TElem);
function OutStack(var Elem:TElem):boolean;
. . .
End;
Для использования данного класса программисту достаточно этих двух методов, то как именно организованы данные значения не имеет.
Если сравнить описание этих процедур с теми, которые были без использования ООП, то будет видно различие. В том случае у процедур будет еще параметры отвечающие за организацию данных. В случае использования массива нужны переменная, указывающая на сам массив и номер элемента, соответствующего вершине стека:
procedure InStack(var Stack:TStack,var TopStack:integer, Elem: TElem);
function OutStack(var Stack:TStack,var TopStack:integer, var Elem: TElem) : boolean;