Взаимосвязь классов и объектов

Введение

Объектно-ориентированное программирование (ООП) целесообразно рассматривать в рамках общей объектно-ориентированной концепции или парадигмы - как взгляд на предметную область, представленную совокупностью объектов, вступающих в отношения друг с другом.

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

Основное достоинство ООП - сокращение количества межмодульных вызовов и уменьшение объемов информации, передаваемой между модулями, по сравнению с модульным программированием. Это достигается за счет более полной локализации данных и интегрирования их с подпрограммами обработки, что позволяет вести практически независимую разработку отдельных частей (классов) программы.

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

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


 

1. Концептуальные основы
объектно-ориентированного программирования



Декомпозиция систем

Как отмечает Эдгар В. Дейкстра, рассматривая программирование как вид человеческой деятельности, «Техника управления сложностью известна с древних времен: "Divide et impera" (разделяй и властвуй)».

Научный метод, позволяющий заменить решение одной большой задачи решением серии меньших, называют «декомпозицией» [1].

Существует, однако, несколько стратегий декомпозиции, среди которых можно выделить следующие.

1. Функциональная или алгоритмическая декомпозиция. Декомпозиция базируется на анализе функций системы. Основанием разбиения на функциональные подсистемы служит общность функций, выполняемых группами элементов.

2. Объектно-ориентированная декомпозиция (декомпозиция по подсистемам). Признак выделения подсистем - сильная связь между элементами по одному из типов отношений (связей), существующих в системе (информационных, логических, иерархических, энергетических и т.п.).

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

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

Можно сказать, что при функциональной декомпозиции система описывается преимущественно глаголами и отглагольными существительными.

Функциональная декомпозиция - самый короткий путь от задачи к программной системе. Однако самый короткий путь не всегда самый лучший.

Альтернативой функциональной или алгоритмической декомпозиции является декомпозиция объектно-ориентированная. При такой стратегии в системе выявляются подсистемы, которые в свою очередь состоят из подсистем и т.д. до некоторого уровня, который представляется «элементарным». Можно сказать, что в этом случае система описывается преимущественно существительными. Результаты такой декомпозиции находятся, конечно, чуть дальше от последовательности команд процессора. Однако у объектно-ориентированной декомпозиции есть существенное преимущество - разбиение системы на структурные единицы выполняется способом, более естественным для человека.

Рассмотрим пример. Пусть необходимо построить программную систему, моделирующую работу банкомата. Первым этапом построения системы является декомпозиция предметной области.

Функциональная декомпозиция дает следующий список задач с их подзадачами.

1. Снять деньги с карты:

· вставить кредитную карту;

· ввести PIN-код;

· ввести запрашиваемую сумму;

· вытащить карту;

· забрать деньги.

2. Положить деньги на карту:

· вставить кредитную карту;

· ввести PIN-код;

· положить купюры в купюроприемник;

· дождаться внесения денежных средств на карту;

· вытащить карту.

Объектно-ориентированная декомпозиция приводит к следующему разложению системы.

1. Считыватель магнитных карт.

2. Клавиатура.

3. Купюроприемник.

4. Устройство выдачи банкнот.

На первый взгляд может показаться, что алгоритмическая декомпозиция предпочтительнее, так как представляет собой перечисление алгоритмов, реализация которых приведет к созданию действующей программы, моделирующей работу банкомата. Однако, если элементы объектно-ориентированной декомпозиции дополнить связанными с ними действиями (например, «Считыватель магнитных карт.Прочитать данные с карты», «Цифровая клавиатура.Ввести PIN-код» и т.д.) и определить, какие действия в какой последовательности и при каких условиях должны выполняться, мы получим действующую модель банкомата.

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

Можно ли утверждать, что объектно-ориентированная декомпозиция является более «правильной» по отношению к алгоритмической?

Важны оба аспекта - и объектно-ориентированная декомпозиция, и алгоритмическая. Разделение по алгоритмам концентрирует внимание на порядке происходящих событий, а разделение по объектам придает особое значение агентам, которые являются либо объектами (тем, кто производит действия), либо субъектами (над кем производится действие).

Опыт показывает, что полезнее начинать именно с объектной декомпозиции.

Понятие класса

Традиционно под классификацией принято понимать процесс группировки объектов исследования или наблюдения в соответствии с их общими признаками. Результатом классификации является классифицированная система (часто называемая так же, как  и процесс, – классификацией), которая, как правило, имеет иерархическое строение. Целью классификации является получение систематизированного описания того или иного сложного процесса или явления.

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

Можно сказать, что в объектно-ориентированной классификации важно максимально полно описать предметную область для того, чтобы затем на основе выявленных сущностей построить программную систему. Основная же цель традиционной классификации - построить удобную, полную и непротиворечивую систему разложения объектов некой предметной области «по полочкам». Это делается преимущественно для того, чтобы упростить общение людей, ее применяющих.

Таким образом, построение качественной объектно-ориентированной классификации невозможно без уяснения того, что следует понимать под понятием «класс».

Класс - это некое множество объектов, имеющих общую структуру и одинаковое поведение.

Любой объект может принадлежать или не принадлежать определенному классу, то есть обладать или не обладать поведением, которое данный класс подразумевает.

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

Рисунок 1.1. Объекты и классы: каждый класс описывает множество индивидуальных объектов

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

Это позволяет говорить, что данные классы образуют иерархию наследования. Такое иерархическое упорядочение абстракций и, следовательно, классов позволяет реализовать еще один «столп» ООП - полиморфизм.

Понятия «наследование», «полиморфизм», а также третье широкоизвестное ключевое понятие ООП - «инкапсуляция» будут подробно рассмотрены в следующих разделах.

Взаимосвязь классов и объектов

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

Выше было приведено определение «класса» через понятие «объект». Совершенно справедливым будет дать следующее определение понятия «объект» через понятие «класс».

Объект – это экземпляр класса.

Несмотря на тавтологичность этих определений (определение в той или иной степени повторяет определяемое понятие), в данном случае этот прием лучше раскрывает взаимосвязь понятий «класс» и «объект».

Из чего же состоит класс? Согласно определению класса наиболее существенными для него являются структура (множество данных, описывающих состояние объектов класса) и поведение.

В программных системах состояние объектов, модулей и программной системы в целом описывается совокупностью переменных, а поведение - совокупностью алгоритмов.

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

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

Во многих процедурных языках программирования реализована синтаксическая конструкция, представляющая собой поименованное множество переменных. В Pascal такая конструкция называется «запись» и определяется ключевым словом «record». В языке C аналогичная конструкция определяется ключевым словом «struct». С некоторыми допущениями можно сказать, что «класс» – это «запись», к которой «приписаны» процедуры и функции, имеющие привилегированный доступ к ее полям. Таким образом, класс - это совокупность полей, определяющих состояние объектов этого класса и методов, ответственных за их поведение. Во многих объектно-ориентированных языках допускается определение «свойств» - элементов, которые также можно отнести к составным частям класса. Свойства широко используются программистами, так как обеспечивают реализацию одного из принципов ООП - инкапсуляцию. Однако по своей природе свойства занимают промежуточное положение между полями и методами и всегда могут быть представлены их совокупностью. В этом смысле свойства являются производными элементами.

В строго объектно-ориентированных языках (например, Smalltalk, Java, C#) любой алгоритм обязательно должен являться составной частью (методом) какого-либо класса. В языках, имеющих процедурные «корни», допускается существование процедур и функций, не привязанных к определенному классу. Такие процедуры и функции называют «свободными». Свободные процедуры – это наследие процедурного подхода. Их использование допускается и в некоторых ситуациях даже бывает оправданно. Однако, обучаясь объектно-ориентированному программированию, их применения лучше избегать.

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

Таким образом, термину «объектно-ориентированное программирование» можно дать следующее определение.

Объе́ктно-ориенти́рованное программи́рование (ООП) — методология программирования, основанная на представлении программы в виде совокупности объектов, каждый из которых является экземпляром определенного класса, а классы образуют иерархию наследования [2].

Контрольные вопросы

1. Какова роль декомпозиции в процессе создания системы?

2. Какие основные стратегии декомпозиции используются в процессе создания информационных систем?

3. Как связаны понятия «класс» и «абстракция»?

4. Что означают уровни абстракции? Приведите пример взаимосвязанных абстракций, расположенных на разных уровнях.

5. Как взаимосвязаны понятия «класс» и «объект»? Приведите примеры классов и объектов.


 



Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: