- •Предисловие
- •Введение в объектно-ориентированное программирование Основные понятия объектно-ориентированного программирования: инкапсуляция, наследование и полиморфизм Объект
- •Наследование и полиморфизм
- •Агрегация
- •Апология ооп
- •Демонстрация преимущества объектно-ориентированного программирования на примере системы вывода графических изображений
- •Реализация с помощью структурных технологий
- •Реализация с помощью объектно-ориентированных технологий
- •Создание классов и объектов в actionscript 2.0
- •Основы создания классов и объектов
- •Объектно-ориентированные, объектные и объектно-базированные языки программирования
- •Квалификаторы доступа и методы доступа Get/Set Первая версия класса библиографических карточек
- •Вторая версия класса библиографических карточек
- •Задание 1
- •Наследование и полиморфизм в actionscript 2.0 Наследование
- •Полиморфизм
- •Задание 2
- •Литература
Реализация с помощью структурных технологий
Итак, требуется разработать подсистему графического вывода, которая позволяет формировать изображения из двух примитивов: прямоугольников и треугольников с использованием методов структурного программирования (рис. 3, а). Для реализации данной подсистемы необходимы структуры, описывающие примитивы прямоугольников и треугольников, два массива для хранения экземпляров каждой такой структуры, управляющий модуль и две подпрограммы, собственно и выводящие на экран эти примитивы (прямоугольники и треугольники), которые будут последовательно осуществлять обход массивов.
Как видно, программа даже для случая использования всего двух примитивов получается достаточно сложной. А теперь, допустим, нам необходимо расширить функциональность данной программы и использовать уже не два, а три примитива. В виде третьего, нового примитива, будет выступать дуга (рис. 3, б). Для того чтобы удовлетворить изменившимся требованиям, необходимо модифицировать программу следующим образом:
Создать структуру, описывающую графический примитив дуги.
Создать массив для вновь созданной структуры.
Написать подпрограмму, выводящую на экран дуги.
Видоизменить управляющий модуль таким образом, чтобы он вызывал вновь созданную подпрограмму.
Как видим, изменения, которые пришлось внести в программу, оказались весьма существенными. Помимо того, что необходимо было создать новые: структуру, массив и подпрограмму, еще пришлось модифицировать уже имеющий модуль. Причем последний пункт является особенно критичным, так как наиболее чреват возникновением ошибок.
Кроме
того, в реальных системах управляющий
модуль был бы уже отлажен и какие-либо
вмешательства в него являлись бы крайне
нежелательными. Более того, не исключена
ситуация, что данный модуль был написан
другим программистом, что только
многократно усугубило бы ситуацию. А в
случае стороннего поставщика мог бы и
вовсе отсутствовать исходный код, что
сделало бы решение данной задачи и вовсе
маловероятным.
Рис. 3. Вывод графики в случае использования структурных технологий
Реализация с помощью объектно-ориентированных технологий
Теперь рассмотрим случай использования объектно-ориентированных технологий. Перед нами стоит сначала все та же задача: разработать подсистему графического вывода изображений, состоящих из прямоугольников и треугольников. Какова будет структура нашей системы? Рассмотрение начнем с реализации собственно примитивов. Теперь вместо структур, содержащих их описания (атрибуты), у нас будут классы, которые помимо собственно атрибутов (длина, высота и т. п.) будут содержать и некоторые методы (рис. 4, а). Хотя в реальных системах будет множество различных методов (включая возможность сохранения / восстановления, дублирования и т. п.), нас будут интересовать только методы, выводящие эти примитивы на экран монитора. Сразу можно заметить, что и прямоугольники, и треугольники: 1) являются геометрическими фигурами и 2) оба они будут обладать способностью отображать себя на экране. Следовательно, целесообразно ввести базовый класс геометрических фигур, в котором будет объявлен метод «Отобразить», являющийся общим для обоих примитивов. Так как не существует геометрической фигуры вообще, а существуют лишь конкретные прямоугольники, треугольники и т. д., то и класс геометрических фигур будет абстрактным, т. е., от него не может быть непосредственно порождено объектов. Этот класс нужен для того, чтобы стать основой для классов-потомков, являющихся классами конкретных фигур. От этого класса они унаследуют атрибуты (например название фигуры)* и методы. Другим назначением класса фигур будет предоставление единого интерфейса для классов-потомков. В самом деле, метод «Отобразить», который в базовом классе лишь объявлен и является виртуальным, посредством полиморфизма будет замещен в классах-потомках и будет иметь конкретную реализацию: для класса прямоугольников - выводить на экран прямоугольник, для класса треугольников - треугольник. Но и тот, и другой методы будут иметь одно и тоже имя - «Отобразить», а выполняться будет совершенно по-разному.
Таким образом, если какой-то объект (клиент) захочет воспользоваться функциональностью объекта, являющегося экземпляром класса той или иной фигуры (сервер), то этому объекту-клиенту вовсе не надо знать, к какому конкретно объекту-серверу он обращается (в нашем случае прямоугольнику или треугольнику). Объект-клиент лишь отдает объекту-серверу команду «Отобразить» посредством вызова одноименного метода, а объект-сервер уже сам знает, что ему надо делать. И именно механизм полиморфизма отвечает за такую «анонимность».
Рис. 4. Вывод графики в случае использования
Объектно-ориентированных технологий
Итак, мы знаем, что объекты классов примитивов имеют одноименный метод «Отобразить», позволяющий отобразить каждый из них правильным образом: прямоугольники прямоугольниками, а треугольники - треугольниками. Теперь требуется ответить на вопрос, можно ли всех их хранить в одном массиве (или каком-либо другом контейнере, например в связанном списке). Оказывается, что можно. В самом деле, даже если мы используем язык со строгой типизацией, когда в том или ином массиве можно хранить объекты лишь определенного класса, нам можно не создавать два массива для прямоугольников и треугольников в отдельности. И прямоугольники, и треугольники являются потомками одного родительского класса - класса геометрических фигур. Следовательно, создав массив геометрических фигур, мы можем хранить в нем прямоугольники и треугольники, выполнив требуемые приведения типов (типы прямоугольников и треугольников приводятся к типу геометрических фигур), что обычно допускается в языках, поддерживающий парадигму ООП. Кроме того, мы можем хранить в таком массиве любые другие объекты, являющиеся экземплярами классов-потомков класса геометрических фигур, что, как мы вскоре увидим, открывает нам очень простой и безопасный путь расширения функциональности.
Итак, мы имеет классы двух примитивов, их родительский класс и массив объектов класса геометрических фигур. Теперь мы можем заполнить его объектами наших примитивов, предварительно осуществив соответствующее приведение типов. А так как все объекты наших классов имеют метод «Отобразить», который также имеется и у родительского класса, который предоставляет единый интерфейс, то посредством полиморфизма объекты, использующие функциональность этих классов, могут не беспокоиться по поводу того, к объекту какого класса они обращаются. Им надо просто вызвать соответствующий метод, после чего будет выполнено требуемое действие.
Исходя из этого, мы пришли к тому, что для реализации вывода нам не только не надо иметь несколько массивов объектов, но нам можно обойтись одним единственным и к тому же достаточно простым методом, обеспечивающим вывод изображения на экран. Этот метод должен всего-навсего осуществить обход массива, в котором содержатся объекты примитивов и вызвать метод «Отобразить» каждого из них. Вот и все. Объекты сами знают, что делать.
Как видим, программа в объектно-ориентированном исполнении получилась значительно проще и изящней. Теперь, как и в случае со структурной реализацией, попробуем ее расширить. А сделать это оказывается очень просто. Надо просто добавить класс требуемого примитива (в нашем случае - класс дуг), порожденного все от того же класса геометрических фигур (рис. 4, б). И на этом процесс модификации закончится. Нам не надо создавать новый массив, новую подпрограмму вывода, не надо обеспечивать вызов этой подпрограммы из управляющего модуля, для чего пришлось бы осуществлять его модификацию. Таким образом, программы, созданные с использованием объектно-ориентированных технологий, являются более изящными и обладают гораздо лучшей расширяемостью по сравнению с технологиями структурного программирования. Кроме того, объектно-ориентированные методы способствуют многократному использованию кода, так как предыдущие решения намного проще использовать в новых проектах, по сравнению с программами, выполненными по структурной методологии. Именно это снискало объектно-ориентированному программированию то лидирующее положение, которое оно сейчас по праву и занимает.
