Объектно-ориентированное программирование
Рефераты >> Программирование и компьютеры >> Объектно-ориентированное программирование

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

Инкапсуляция является важнейшим свойством объектов, на котором строится объектно-ориентированное программирование. Инкапсуляция заключается в том, что объект скрывает в себе детали, которые несущественны для использования объекта. В традиционном подходе к программированию с использованием глобальных переменных программист не был застрахован от ошибок, связанных с использованием процедур, не предназначенных для обработки данных, связанных с этими переменными. Предположим, например, что имеется «не-ООП» программа, предназначенная для начисления заработной платы сотрудникам некой организации, а в программе имеются два массива. Один массив хранит величину заработной платы, а другой – телефонные номера сотрудников (для составления отчёта для налоговой инспекции). Что произойдёт, если программист случайно перепутает эти массивы? Очевидно, для бухгалтерии начнутся тяжёлые времена. «Жёсткое» связание данных и процедур их обработки в одном объекте позволит избежать неприятностей такого рода. Инкапсуляция и является средством организации доступа к данным только через соответствующие методы.

В нашем примере описание объекта процедура инициализации Init и функции GetX и GetY уже не существуют как отдельные самостоятельные объекты. Это неотъемлемые части объектного типа Location. Если в программе имеется описание нескольких переменных указанного типа, то для каждой переменной резервируется своя собственная область памяти для хранения данных, а указатели на точки входа в процедуру и функции – общие. Вызов каждого метода возможен только с помощью составного имени, явно указывающего, для обработки каких данных предназначен данный метод.

5. Наследование

Наследование – это ещё одно базовое понятие объектно-ориентированного программирования. Наследование позволяет определять новые объекты, используя свойства прежних, дополняя или изменяя их. Объект-наследник получает все поля и методы «родителя», к которым он может добавить свои собственные поля и методы или заменить («перекрыть») их своими методами. Пример описания объекта-наследника даётся ниже:

Tipe

Point = object(Location)

Visible: Boolean;

Procedure Int(IntX, IntY: Integer);

Procedure Show;

Procedure Hide;

Function IsVisible: Boolean;

Procedure MoveTo(NewX, NewY: Integer);

End;

Наследником здесь является объект Point, описывающий графическую точку, а родителем – объект Location. Наследник не содержит описание полей и методов родителя. Имя последнего указывается в круглых скобках после слова object. Из методов наследника можно вызывать методы родителя. Для создания наследника не требуется иметь исходный текст объекта родителя. Объект-родитель может быть уже в составе оттранслированного модуля.

В чём привлекательность наследования? Если некий объект был уже определён и отлажен, он может быть использован и в других программах. При этом может оказаться, что новая задача отличается от предыдущей, и возникает необходимость некоторой модификации как данных, так и методов их обработки. Программисту приходится решать дилемму – создания объектов заново или использовать результаты предыдущей работы, применяя механизм наследования. Первый путь менее эффективен, так как требует дополнительных затрат времени на отладку и тестирование. Во втором случае часть этой работы оказывается выполненной, что сокращает время на разработку новой программы. Программист при этом может и не знать деталей реализации объекта-родителя.

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

6. Виртуальные методы

Наследование позволяет создавать иерархические, связанные отношениями подчинения, структуры данных. Следует, однако, заметить, что при использовании этой возможности могут возникнуть проблемы. Предположим, что в нашей графической программе необходимо определить объект Circle, который является потомком другого объекта Point:

Type

Circle = object (point)

Radius: Integer;

Procedure Show;

Procedure Hide;

Procedure Expand(ExpandBy: Integer);

Procedure Contact(ContactBy: Integer);

End;

Новый объект Circle соответствует окружности. Поскольку свойства окружности отличаются от свойств точки, в объекте-наследнике придется изменять процедуры Show и Hide, которые отображают окружность и удаляют её изображение с экрана. Может оказаться, что метод Init (см. предыдущий пример) объекта Circle, унаследованный от объекта Point, также использует методы Show и Hide, впредь во время трансляции объекта Point использует ссылки на старые методы. Очевидно в объекте Circle они работать не будут. Можно, конечно, попытаться «перекрыть» метод Init. Чтобы это сделать, нам придётся полностью воспроизвести текст метода. Это усложни работу, да и не всегда возможно, поскольку исходного текста программы может не оказаться под рукой (если объект-родитель уже находиться в оттранслированном модуле).

Для решения этой проблемы используется виртуальный метод. Связь между виртуальным методом и вызывающими их процедурами устанавливается не во время трансляции (это называется ранним связанием), а во время выполнения программы (позднее связание.

Чтобы использовать виртуальный метод, необходимо в описании объекта после заголовка метода добавить ключевое слово virtual. Заголовки виртуальных методов родителя и наследника должны в точности совпадать. Инициализация экземпляра объекта, имеющего виртуальные методы, должна выполняться с помощью специального метода – конструктора. Конструктор обычно присваивает полям объекта начальные значения и выполняет другие действия по инициализации объекта. В заголовке метода-конструктора слово procedure заменяется словом constructor. Действия обратные действиям конструктора, выполняет ещё один специальный метод – деструктор. Он описывается словом destructor.

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

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

Заметим, что конструктор или деструктор, могут быть «пустыми», то есть не содержать операторов. Весь необходимый код в этом случае создается при трансляции ключевых слов construct и destruct.


Страница: