Как правильно писать тесты 46 Цикл разработки 46 Структура проекта с тестами 51 Утверждения (Asserts) 52 Утверждения в форме ограничений 54 Категории 56

Вид материалаТесты

Содержание


Основные принципы объектно-ориентированного программирования (окончание) Полиморфизм
Агрегация и композия
Подобный материал:
1   2   3   4   5   6   7   8   9   ...   47

Основные принципы объектно-ориентированного программирования (окончание)4

Полиморфизм


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


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


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


Есть цифра 5. Вопрос: "Какого она типа?". Целое? Ни разу. С плавающей точкой?. Еще чего. Правильный ответ - тип цифры 5 не известен. Точно, ее тип будет известен только тогда, когда она будет передаваться в какое-то выражение. Т.е. 5+3.14 -> float, 5+3 -> int и.т.д. Вот это и есть полиморфизм.
Т.е. полиморфизм - способность объекта принадлежать разным типам данных в зависимости от различных (внешних по отношению к объекту) условий. Оператор «+» в данном случае перегружается, в зависимости от типа данных, к которым он применяется (целый тип, вещественный тип наследуются от типа «число»).

В ООП понятие класс можно расматривать с 3-х точек зрения "класс-как-тип", "класс-как-интерфейс", и "класс-как-поведение". Соответственно с тех же точек зрения можно рассматривать и полиморфизм.

Отношения


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

• Маргаритка - цветок.

• Роза - (другой) цветок.

• Красная и желтая розы - розы.

• Лепесток является частью обоих видов цветов.

• Божьи коровки питаются вредителями, поражающими некоторые цветы.

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

Известны три основных типа отношений между классами. Во-первых, это отношение "обобщение/специализация" (общее и частное), известное как "is-a" (является разновидностью). Розы – это цветы, что значит: розы являются специализированным частным случаем, разновидностью, подклассом более общего класса "цветы". Во-вторых, это отношение "целое/ часть", известное как "part of". Так, лепестки являются частью цветов. В-третьих, это семантические, смысловые отношения, ассоциации. Например, божьи коровки ассоциируются с цветами - хотя, казалось бы, что у них общего. Или вот: розы и свечи - и то, и другое можно использовать для украшения стола.

Обычно аналитик констатирует наличие ассоциации и, постепенно уточняя проект, превращает ее в какую-то более специализированную связь.


Отношение «является разновидностью» в объектно-ориентированных языках описывается с помощью наследования.


Агрегация и композия

Отношение «часть-целое» описывается с помощью агрегации или ее частного случая – композиции.


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


Агрегация (aggregation) может означать физическое вхождение одного объекта в другой, но не обязательно. Например, Самолет имеет крылья, двигатель, хвост и т.д. Иногда агрегация соответствует физическому объекту, иногда это более абстрактное понятие (например, классы Клуб или Пользователь).

Агрегация облегчает предоставление объектам информации друг о друге.

Однако с введением агрегации возникают несколько вопросов. Может ли внутренний объект посылать сообщения контейнеру? Т.е. взаимосвязь симметричная или нет? Самый важный вопрос: должна ли быть агрегация по ссылке или по значению?

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

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

Пример: машина имеет двигатель.

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


Агрегация по ссылке разделяет времена жизни контейнера и внутреннего объекта. Контейнер может не владеть содержащимися в них объектами или содержимое может меняться со временем. Уничтожение контейнера не уничтожает его содержимое. Агрегация по ссылке позволяет части быть независимой от целого. Пример: курс и студенты.


Использование

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

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

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


Ассоциации

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

Ассоциации имеют кардинальность (мощность или грубо говоря, количество участников), т.е. это отношение может быть типа один-к-одному, один-ко-многим, многие-ко-многим.


Обобщение

Это наиболее тонкий вид отношений между классами. Известна такая характеристика для этого процесса: «generics» (групповой; родовой; общий).

Отношение обобщения возникает в ситуации, когда поведение класса может быть обобщено на разные типы. Цель – разделить определение собственно класса и его поведения, которое будет отличаться в зависимости от конкретного типа.

Например, класс Стек должен вести себя одинаково вне зависимости от того, что он содержит: Собак (Dog), Целые числа (int), Строки (String) или что-то еще. Нам не придется вводить отдельные классы DogStack, IntStack и т.д. с почти одинаковыми методами. Общим элементом для семейства стековых классов будет тип данных, который в нем будет содержаться. Предлагается абстрагироваться от конкретного типа данных и параметризовать класс Стек неким обобщенным типом, который будет конкретизироваться только при создании объекта класса Стек для хранения объектов конкретного типа. Решение о конкретизации переносится в точку создания объекта.