Базовые понятия объектно-ориентированного программирования
При использовании ООП основными действующими лицами являются не переменные, а объекты.
Объектам Visual Basic присуща функциональность. Иными словами, они действуют определенным образом и могут откликаться на определенные ситуации. При этом если свойства объекта определяют его внешний вид и поведение, то методы объекта – те задачи, которые может выполнить данный объект. Методы по сути дела представляют собой сегмент программного кода, внедренный в объект.
Существует определенный формат программного кода, задающего установку свойства и использование метода:
Объект.Свойство = Значение
Объект.Метод [Параметр1 [...]]
Здесь Объект – имя настраиваемого объекта; Свойство – характеристика, которую нужно изменить; Метод – команда, которая используется для изменения объекта; Значение – новая установка свойства; Параметр – аргумент, используемый методом.
Пусть необходимо написать программу, которая будет рисовать на экране снеговика, состоящего и кругов какого-либо определенного цвета. Необходимо предусмотреть возможность перемещения снеговика по экрану в различных направлениях – процедура Move. Сделать возможным изменение цвета для всех кругов, из которых состоит снеговик.
Все крути можно представить в виде самостоятельных объектов с одинаковой структурой, которые отличаются друг от друга лишь значениями параметров. Действие процедур Draw (рисование круга), Move (перемещение круга) и ChangeColor (смена цвета круга), идентичны применительно к каждому из кругов. Все круги являются объектами, которые имеют одинаковую структуру (радиус, координаты центра, цвет) и ведут себя схожим образом при выполнении любого действия (рисование, перемещение, изменение цвета), т.е. все они принадлежат одному и тому же семейству.
С точки зрения объектно-ориентированного программирования все "действующие лица" программы представляют собой объекты, каждый из которых является элементом (экземпляром) какого-либо класса. Параметры объекта (радиус, цвет и т. п.) называются его свойствами, а процедуры или функции, которые он выполняет в ответ на какой-либо запрос (поменять цвет, переместиться и т. п.), называются методами. При этом метод, который должен вызываться в ответ на запрос, определяется классом, экземпляром которого является данный объект. И наоборот, если объекты принадлежат одному и тому же классу, то они должны вызывать одинаковые методы в ответ на один и тот же запрос.
Представление свойств и методов как неотъемлемых частей любого объекта носит название инкапсуляции, т.е. в этом случае объект можно представить как своеобразную оболочку (капсулу), которая "окружает" программный код (методы) и данные (свойства). На рис. 1 приведена иллюстрация этого важного понятия ООП.
ОБЪЕКТ | ||||
Свойства | Методы | |||
Рис.1. Иллюстрация понятия инкапсуляции
Пусть класс, которому принадлежат все объекты-круги, называется Round.
Свойствами класса Round являются следующие:
– R – радиус круга;
– X, Y – координаты центра круга;
– Color – цвет круга.
Методы класса Round:
– Draw – рисует круг с заданными параметрами;
– Move – перемещает круг на определенное расстояние в выбранном направлении;
– ChangeColor – изменяет цвет крута.
Для того чтобы нарисовать снеговика, потребуются три объекта-круга. Верхний из них можно назвать Head, средний – Body, a нижний – Foot. Все эти объекты принадлежат классу Round. Следовательно, все они имеют одинаковые свойства (R, X, Y, Color) и вызывают одинаковые методы (Draw, Move, ChangeColor) в ответ на одни и те же запросы.
Таким образом, в ООП принципы абстрагирования и сокрытия данных нашли свое максимальное отражение. Программа состоит из независимых блоков, которые могут использоваться и в других приложениях. ООП зачастую позволяет создавать конечный продукт просто путем соединения нескольких готовых блоков, написанных ранее.
Наследование
Пусть необходимо нарисовать снеговика с глазами, которые должны время от времени мигать. Все остальные свойства и методы у объектов-глаз должны быть такими же, как и у объектов-кругов, принадлежащих классу Round, т. е, глаза снеговика тоже нужно перемещать по экрану вместе с остальными кругами, а также должна оставаться возможность изменения их цвета. Для реализации этого дополнения можно создать еще один класс – Eyes (глаза), в котором будут те же свойства и методы, что и в Round, но еще будет добавлен метод Blink (мигание). Однако при этом придется для класса Eyes заново создавать все свойства и методы, которые уже были описаны для Round.
Чтобы не выполнять подобную двойную работу, в ООП существует механизм наследования. Этот механизм реализуется путем создания иерархической структуры классов. Вначале создается класс Round, для которого описываются все свойства и методы. Он располагается в основании иерархической структуры. Затем создается еще один класс под названием Eyes, в котором описывается новый метод Blink, а все остальные свойства и методы остаются без изменений, т.е. класс Eyes наследует все свойства и методы Round и, в то же время, включает в себя дополнительный метод Blink. В иерархической структуре Eyes следует за классом Round, и в этом случае говорят, что Round является предком (или родительским классом) для Eyes. В свою очередь, Eyes является потомком (или дочерним классом для Round.
Наследованием называется возможность доступа объектов, принадлежащих классу-потомку, к методам и свойствам класса-предка. Иллюстрация наследования приведена в табл. 1.
Таким образом, применение наследования в ООП ведет к значительному уменьшению объема программы и повышению ее функциональности.
Полиморфизм
Этот термин относится к таким переменным или параметрам процедур (функций), которые в процессе выполнения программы могут принимать значения разных типов. Процедуры (функции), имеющие полиморфные параметры, также называются полиморфными.
Пусть необходимо рисовать на экране не только круги, но и другие геометрические фигуры (например, прямоугольники), причем с ними нужно выполнять те же самые действия, которые были описаны ранее (рисовать, перемещать, изменять цвет фигуры). Но для того, чтобы нарисовать прямоугольник, необходимо знать координаты какой-либо его вершины (например, левой верхней), а также его длину и ширину.
Таблица 1. Наследование классом Eyes свойств и методов Round
Round | Свойства |
R | |
X | |
Y | |
Color | |
Методы | |
Draw | |
Move | |
ChangeColor | |
Eyes | Свойства |
R | |
X | |
Y | |
Color | |
Методы | |
Draw | |
Move | |
ChangeColor | |
Blink |
Для реализации приведенных требований следует создать класс Rect, являющийся потомком Round, и применительно к нему X и Y – это координаты выбранной вершины прямоугольника, a R – его длина (или ширина). Но в этом случае придется описать еще одно свойство для обозначения ширины (или длины). Очевидно, что при работе с подобными классами легко может возникнуть путаница в использовании свойств, и причина этого – узкая направленность класса Round, который ориентирован на работу только с определенной геометрической фигурой.
Чтобы сделать Round более универсальным, т.е. пригодным для изображения большего числа геометрических фигур, следует изменить его свойства следующим образом. Вместо радиуса и координат центра нужно описать такие свойства как:
– Тор – координата верхний границы фигуры;
– Left – координата левой границы фигуры;
– Height – высота фигуры;
– Width – ширина фигуры.
По этим свойствам легко можно определить недостающие координаты для любой фигуры. Например, для получения всех координат прямоугольника (или квадрата) необходимо к координате левой границы прибавлять ширину, а из верхней вычитать высоту. Пусть
Тор = 80,
Left = 20,
Height = 40,
Width = 60.
Тогда
– правая граница равна
Left + Width = 80,
– нижняя равна
Тор – Height = 40.
Следовательно, данный прямоугольник имеет следующие координаты (первая координата – для горизонтальной оси, вторая – для вертикальной): А(20, 80), В(80, 80), С(20, 40), D(80, 40).
Теперь на основе предка Round с описанным выше новым набором свойств можно создать потомка Rect для изображения прямоугольников. Однако методика рисования в этом случае должна отличаться от той, которая использовалась при работе с кругами. Т.е. необходимо, чтобы для Rect содержимое унаследованного метода Draw отличалось от родительского, в противном случае, если вызывать Draw для объекта, принадлежащего классу Rect, то на экране все равно будет нарисован круг, а не прямоугольник.
Чтобы этого избежать, необходимо для Rect описать свой метод Draw. Тогда для объекта, принадлежащего классу Round, вызов Draw будет означать изображение на экране круга, а для объекта из Rect – прямоугольника. Т.е. методы с одним и тем же именем Draw отвечают за разные действия в зависимости от того, объекту какого класса необходимо выполнить рисование. Подобная ситуация в ООП носит название полиморфизма. Графическая интерпретация описанного примера полиморфизма в ООП приведена на рис. 2.
Классы | Метод | Действия | ||
Rect | Draw | Рисует прямоугольник | ||
Round | Рисует круг |
Рис 2. Полиморфизм при вызове метода Draw объемами классов Rect
и Round