Информационный сайт

 

Реклама
bulletinsite.net -> Книги на сайте -> Программисту -> Мизрохи С.В. -> "Turbo Pascal и объектно-ориентированное программирование" -> 76

Turbo Pascal и объектно-ориентированное программирование - Мизрохи С.В.

Мизрохи С.В. Turbo Pascal и объектно-ориентированное программирование — М.: Финансы и статистика , 1992. — 192 c.
ISBN 5-279-00903-2
Скачать (прямая ссылка): efektispolzc2000.djvu
Предыдущая << 1 .. 70 71 72 73 74 75 < 76 > 77 78 79 80 81 82 .. 105 >> Следующая

Правило 40. Моделируйте отношения «содержит» и «реализуется посредством» с помощью вложения
Вложение - это метод построения одного класса поверх другого, когда один класс включает в себя объект другого класса в качестве элемента данных. Например:
class Address { ... }; class PhoneNumber { . . class Person { public:
// Чье-либо место жительства.
};
private:
string name; Address address; PhoneNumber voiceNumber; PhoneNumber faxNumber;
};
Il Вложенный объект. Il To же. II To же. II To же.
F
В данном случае о классе Person говорят, что в него вложены классы string, Address и PhoneNumber, поскольку он содержит переменные этих типов. Термин вложение имеет ряд синонимов. Данное понятие тоже обозначается такими Терминами, как композиция, содержание и включение.
В правиле 35 объясняется, что открытое наследование означает «класс есть Разновидность класса». В противоположность этому вложение означает либо <¦ класс содержит класс», либо «класс реализуется посредством класса».
Вышеприведенный класс Person демонстрирует взаимосвязь типа «класс содержит класс». Объект Person имеет имя, адрес и номера телефонов для голосо-вого и факсимильного общения. Нельзя сказать, что человек есть разновидность Имени, или что человек есть разновидность адреса. Можно сказать, что человек ^меет («содержит») имя и адрес. Большинство людей не испытывает затруднений в проведении подобных различий, поэтому путаница между «есть разновидность» и «содержит» возникает сравнительно редко.
else if (pea = dynamic_cast<CheckingAccount*>(*p) ) { pca->creditlnterest();
}
else {
error ("Unknown account type 1 ") ;
}
Ї Наследование и ООП
Чуть сложнее провести различие между отношениями «есть разновидность» и «реализуется посредством». Предположим, например, что вам необходим шаблон для классов, представляющих множества произвольных объектов, то есть коллекции без дубликатов. Поскольку повторное использование - это великолепная вещь, и вы к тому же предусмотрительно ознакомились с обзором стандартной библиотеки С++ в правиле 49, ваше первое побуждение - применить библиотечный шаблон set. В конце концов, зачем писать новый шаблон, когда есть возможность использовать уже готовый?
Однако, углубившись в документацию по set, вы обнаружите ограничение, неприемлемое для вашего приложения: set требует, чтобы содержащиеся в нем элементы были полностью упорядочены, то есть для каждой пары объектов а и b из множества можно было бы определить, что либо а<Ь, либо Ь<а.
Применительно к некоторым типам удовлетворить этому требованию достаточно легко, а полная упорядоченность объектов позволяет шаблону set дать пользователям достаточно привлекательные гарантии относительно производительности. (Подробности, касающиеся гарантий производительности стандартной библиотеки, приводятся в правиле 49.) Однако вам необходимо нечто более общее: класс, подобный set, объекты которого могут не удовлетворять критерию полного упорядочения, а единственное требование, предъявляемое к ним, - возможность определения для объектов а и b одного типа, что а==Ь. Это более скромное требование гораздо лучше подходит для того, чтобы моделировать такие характеристики, как цвет, например. Меньше ли красный, чем зеленый, или зеленый меньше, чем красный? Для нашего приложения, по-видимому, придется написать свой собственный шаблон.
Тем не менее повторное использование - это великолепная вещь. Будучи экспертом в области структур данных, вы знаете, что при наличии практически безграничного набора возможных реализаций один из самых простых способов -применение связных списков. Что дальше? Шаблон list (который генерирует классы связных списков) уже имеется в стандартной библиотеке! Вы принимаете решение использовать его повторно.
В частности, вы решаете, что создаваемый вами шаблон Set должен наследовать от list, то есть Set<T> будет наследовать от list<T>. В итоге в вашей реализации объект Set будет выступать как объект list. Соответственно, вы определяете Set следующим образом:
// Неправильный способ использовать list для определения Set. template<class Т>
class Set: public list<T> { ... };
До сих пор все вроде бы шло превосходно, но, если присмотреться, в код вкралась ошибка. Как объясняется в правиле 35, если D есть разновидность В, все, что верно для В, также верно и для D. Однако объект list может содержать дубликаты, поэтому, если значение 3051 вставляется в список list<int> дважды, список будет содержать две копии 3051. Напротив, Set не может содержать дубликатов, поэтому, если значение 3051 вставляется в Set< int > дважды, множество содержит только одну копию данного значения. Следовательно, утверждение, что объект класса Set есть разновидность объекта типа list, является ложным: ведь некоторые вещи, которые верны для объектов list, неверны для объектов Set.
Правило 40 ¦¦BiHiEi]
Из-за того что отношение между данными объектами не основано на принципе «есть разновидность», открытое наследование - неправильный способ моделирования этой взаимосвязи. Правильный подход обеспечит понимание того, что объект Set может быть реализован посредством объекта list:
Предыдущая << 1 .. 70 71 72 73 74 75 < 76 > 77 78 79 80 81 82 .. 105 >> Следующая
Реклама
Авторские права © 2009 AdsNet. Все права защищены.
Rambler's Top100