Объектно-ориентированное программирование
В основе того или иного языка программирования лежит некоторая руководящая идея, оказывающая существенное влияние на стиль соответствующих программ. Исторически первой была идея процедурного структурирования, в соответствии с которой программист должен был решить, какие именно процедуры он будет использовать в своей программе, а затем выбрать наилучшие алгоритмы для их реализации. Типичным представителем являлся Фортран. По мере прогресса в области вычислительной математики, акцент в программировании стал смещаться с процедур в сторону организации данных. Паскаль, СИ, Ада имеют более или менее развитые структуры типов данных. Логическим следствием развития этого направления стал модульный подход к разработке программ, характеризующийся стремлением “спрятать” данные и процедуры внутрь модуля.
Начиная с языка Симула 67, в программировании наметился новый подход, который получил название объектно-ориентированного программирования (ООП). Его руководящей идеей является стремление связать данные с обрабатывающими эти данные процедурами в единое целое – объект. Фактически ООП можно рассматривать как модульное программирование нового уровня, когда вместо во многом случайного, механистического объединения в модуле процедур и данных акцент делается на смысловую связь полей и методов объекта.
3.1. Что такое объект?
В терминах Паскаля, объект во многом схож с записью, которая является оболочкой для объединения нескольких связанных элементов под одним именем. Предположим, необходимо разработать программу вывода платежной ведомости, печатающую отчет и показывающую, сколько нужно выплатить каждому служащему института. Запись можно организовать следующим образом:
Type TPerson = record
Name : string[25];
Dolgn : string[25];
Stavka : Real;
end;
Var Person : TPerson;
Здесь TPerson является типом записи, т.е. шаблоном, используемым компилятором для создания переменных типа запись. Переменная Person является экземпляром этого типа.
TPerson представляет два уровня абстракции. Можно рассматривать поля Name, Dolgn и Stavka по отдельности, а когда речь идет о полях, работающих одновременно для описания конкретного работника, можно рассматривать их совокупность как TPerson.
Предположим, что программа должна учитывать выплату денег студентам, преподавателям и сотрудникам института. В каждой категории выплата денег производится особым образом. Например, для определения размера стипендии необходимо знать средний балл студента. Можно построить запись TStudent вида:
TStudent = record
Name : string[25];
Dolgn : string[25];
Stavka : Real;
Ball : Real;
end;
Можно сохранить тип TРerson внутри типа TStudent:
TStudent = record
Student : TPerson;
Ball : Real;
end;
Tип TStudent является дочерним типом для типа TPerson. TStudent наследует все, что принадлежит TPerson, и кроме того имеет кое-что новое, что делает TStudent уникальным.
В Турбо Паскале существует еще один тип данных, который обладает таким свойством. Это объектный тип. Типы данных в этой новой категории определяются с помощью нового зарезервированного слова Оbject.
Type
TPerson = Object
Name : string[25];
Dolgn : string[25];
Stavka : Real;
end;
TStudent = Object (TPerson)
Ball : Real;
end;
Здесь использование скобок означает наследование. TPerson является родительским типом, а TStudent – дочерним типом. Можно определить дочерний тип к типу TStudent и т.д. Большая часть конструирования объектно-ориентированных прикладных программ состоит в построении такой иерархии объектов.
Экземпляры объектных типов описываются в точности так же, как в Паскале описывается любая переменная, либо статическая, либо указатель, ссылающийся на размещенную в динамической памяти переменную:
Type
PStudent = ^TStudent;
Var
Student : TStudent;
DynaStudent : PStudent;
Можно обратиться к полю объекта в точности так же, как к полю обычной записи, либо с помощью оператора With, либо путем уточнения имени с помощью точки. Например:
Student.Stavka := 145;
With Student do
Begin
Name := ‘Степанов Сергей Петрович’;
Ball := 4.87;
End;
Наследуемые поля являются столь же доступными, как если бы они были объявлены внутри типа объекта.
Можно написать специальные процедуры, которые будут изменять содержимое полей. Обычно существует проблема инициализации полей. Для объекта TPerson возможна такая инициализирующая процедура:
Procedure Init (Var Person : TPerson; Nm, Dg : String; Sv : Real);
Begin
With Person Do
Begin Name := Nm; Dolgn := Dg; Stavka := Sv; End;
End;
Принципы объектно-ориентированного программирования требуют, чтобы к полям объектов обращение происходило с помощью специальных процедур, поэтому кроме полей в объекте описывают еще и процедуры, с помощью которых к этим полям обращаются. Такие процедуры называются методами. Поля и методы являются составными частями новой структуры, называемой объектом.
Type
TPerson = Object
Name : string[25];
Dolgn : string[25];
Stavka : Real;
Procedure Init (Nm, Dg : String; Sv : Real);
end;
Сами методы описываются вне определения объекта как отдельная процедура или функция.
Procedure TPerson.Init;
Begin
With Person Do
Begin Name := Nm; Dolgn := Dg; Stavka := Sv; End;
End;
Процесс определения методов объектов напоминает модули Турбо Паскаля. Внутри объекта метод определяется заголовком процедуры или функции подобно интерфейсной части модуля. Описание методов внутри объекта только указывает действия, но не определяет, каким образом они будут выполнены. Сами методы описываются вне определения объекта как отдельная процедура или функция. В заголовках методов указывается имя типа-объекта и после точки – имя метода.
Объект – это такая структура, компонентами которой являются взаимосвязанные данные различных типов и использующие эти данные процедуры и функции. Компоненты-данные называются полями объекта, а компоненты-процедуры и функции называются методами.