Лекции.Орг


Поиск:




Категории:

Астрономия
Биология
География
Другие языки
Интернет
Информатика
История
Культура
Литература
Логика
Математика
Медицина
Механика
Охрана труда
Педагогика
Политика
Право
Психология
Религия
Риторика
Социология
Спорт
Строительство
Технология
Транспорт
Физика
Философия
Финансы
Химия
Экология
Экономика
Электроника

 

 

 

 


Композиция как альтернатива множественному наследованию




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

Композиция – это описание объекта как состоящего из других объектов (отношение агрегации, или включения как составной части) или находящегося с ними в отношении ассоциации (объединения независимых объектов). Если наследование характеризуется отношением “is-a” (“это есть”, “является”), то композиция характеризуется отношением “has-a” (“имеет в своём составе”, “состоит из”) и “use-a” (“использует”).

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

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

Шофёр также является неотъемлемой частью автомобиля, но вряд ли можно считать, что автомобиль состоит из шофёра и других частей. Но можно говорить, что у автомобиля обязательно должен быть шофёр. Либо говорить, что шофёр использует автомобиль. Отношение объекта “автомобиль” и объекта “шофёр” гораздо слабее, чем агрегация, но всё-таки весьма сильное – это композиция в узком смысле этого слова.

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

С точки зрения программирования на Java композиция любого вида - это наличие в объекте поля ссылочного типа. Вид композиции определяется условиями создания связанного с этой ссылочной переменной объекта и изменения этой ссылки. Если такой вспомогательный объект создаётся одновременно с главным объектом и “умирает” вместе с ним – это агрегация. В противном случае это или композиция в узком смысле слова, или ассоциация.

Композиция во многих случаях может служить альтернативой множественному наследованию, причём именно в тех ситуациях, когда наследование интерфейсов “не работает”. Это бывает в случаях, когда надо унаследовать от двух или более классов их поля и методы.

Приведём пример. Пусть у нас имеются классы Car (“Автомобиль”), класс Driver (“Шофёр”) и класс Speed (“Скорость”). И пусть это совершенно независимые классы. Зададим класс MovingCar (“движущийся автомобиль”) как

 

public class MovingCar extends Car{

Driver driver;

Speed speed;

}

 

Особенностью объектов MovingCar будет то, что они включают в себя не только особенности поведения автомобиля, но и все особенности объектов типа Driver и Speed. Например, автомобиль “знает” своего водителя: если у нас имеется объект movingCar, то movingCar.driver обеспечит доступ к объекту “водитель” (если, конечно, ссылка не равна null). В результате чего можно будет пользоваться общедоступными (и только!) методами этого объекта. То же относится к полю speed. И нам не надо строить гибридный класс-монстр, в котором от родителей Car, Driver и Speed унаследовано по механизму множественного наследования нечто вроде машино-кентавра, где шофёра скрестили с автомобилем. Или заниматься реализацией в классе-наследнике интерфейсов, описывающих взаимодействие автомобиля с шофёром и измерение/задание скорости.

Но у композиции имеется заметный недостаток: для получившегося класса имеется существенное ограничение при использовании полиморфизма. Ведь он не является наследником классов Driver и Speed. Поэтому полиморфный код, написанный для объектов типа Driver и Speed, для объектов типа MovingCar работать не будет. И хотя он будет работать для соответствующих полей movingCar.driver и movingCar.speed, это не всегда помогает. Например, если объект должен помещаться в список. Тем не менее часто использование композиции является гораздо более удачным решением, чем множественное наследование.

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


Краткие итоги по главе 8

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

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

ü Интерфейс определяет методы, которые должны быть реализованы классом-наследником этого интерфейса.

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

ü С помощью переменной типа интерфейс разрешается вызывать только методы, декларированные в данном интерфейсе, а не любые методы данного объекта.

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

ü Наследование характеризуется отношением “is-a” (“это есть”, “является”), а композиция - отношением “has-a” (“имеет в своём составе”, “состоит из”) и “use-a” (“использует”).

ü Сочетание множественного наследования интерфейсов и композиции в подавляющем большинстве случаев является полноценной альтернативой множественному наследованию классов.

 

Типичные ошибки:

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

 

Задания

  • Написать реализацию класса Square – наследника ScalableFigure. Класс должен располагаться в пакете AdditionalFigures.
  • В пакете AdditionalFigures задать интерфейс IScalable.
  • В качестве класса, реализующего этот интерфейс, написать абстрактный класс StretchableFigure. Класс должен располагаться в пакете AdditionalFigures.
  • Написать реализацию класса Rectangle – наследника StretchableFigure. Класс должен располагаться в пакете AdditionalFigures.
  • Написать приложение, в котором в зависимости от выбранной радиокнопки создаётся и отрисовывается на панели в произвольном месте, не выходящем за пределы панели, точка, окружность, квадрат или прямоугольник. По нажатию на кнопки “Создать объект”, “show”, “hide”, “moveTo” должны выполняться соответствующие методы для последнего созданного объекта.
  • Усложнить копию данного приложения, добавив на форму компонент с прокручивающимся или выпадающим списком с именами объектов. Имя объекта должно состоять из имени, соответствующего типу, и порядкового номера (dot1, circle3 и т.п.). По нажатию на кнопки “Создать объект”, “show”, “hide”, “moveTo” должны выполняться соответствующие методы для объекта, выделенного в списке.
  • Добавить кнопки “Изменить размер” и “Растянуть объект”. В случае, если объект поддерживает интерфейс ScalableFigure, по нажатию первой из них он должен менять размер. Если он поддерживает интерфейс, по нажатию второй он должен растягиваться или сплющиваться в зависимости от значения в соответствующем пункте ввода.
  • В пакете AdditionalFigures написать интерфейс IBordered, обеспечивающий поддержку методов, необходимых для рисования границы (border) заданной ширины и цвета вокруг графического объекта. Реализовать этот интерфейс в классах BorderedCircle, BorderedSquare, BorderedRectangle.





Поделиться с друзьями:


Дата добавления: 2017-02-28; Мы поможем в написании ваших работ!; просмотров: 781 | Нарушение авторских прав


Поиск на сайте:

Лучшие изречения:

Стремитесь не к успеху, а к ценностям, которые он дает © Альберт Эйнштейн
==> читать все изречения...

2206 - | 2159 -


© 2015-2025 lektsii.org - Контакты - Последнее добавление

Ген: 0.011 с.