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

 

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

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

Мизрохи С.В. Turbo Pascal и объектно-ориентированное программирование — М.: Финансы и статистика , 1992. — 192 c.
ISBN 5-279-00903-2
Скачать (прямая ссылка): efektispolzc2000.djvu
Предыдущая << 1 .. 81 82 83 84 85 86 < 87 > 88 89 90 91 92 93 .. 105 >> Следующая

};
Обратите внимание, насколько проще стала конструкция. В ней встречается только одиночное наследование и, более того, только открытое наследование. Классы Grasshopper и Cricket определяют исключительно функции, уточняющие поведение; функции dance и sing, наследуемые от Insect, остаются неизменными. Уильям Оккам остался бы доволен.
Хотя эта конструкция проще, чем конструкция с использованием множественного наследования, на первый взгляд она может показаться хуже. В конце концов, в отличие от подхода, основанного на использовании множественного наследования, применение простого наследования требует введения совершенно нового класса. Зачем вводить дополнительный класс, если в этом нет необходимости?
•I Здесь мы неизбежно сталкиваемся с соблазном использования множественного наследования. При поверхностном рассмотрении интерфейс множественного
Правило 44
1 IACl
наследования кажется более легким. Он не требует добавления новых классов, и хотя необходимо добавить в класс Grasshopper несколько новых виртуальных функций, это не составляет проблемы, поскольку такие функции все равно где-то пришлось бы объявлять.
Представьте себе программиста, поддерживающего большую библиотеку классов С++, к которой необходимо добавить новый класс, подобно тому как Cricket должен быть добавлен к существующей иерархии CartoonCharacter/ Grasshopper. Программист знает, что существующей иерархией пользуются очень и очень многие, поэтому чем больше изменений вносится в библиотеку, тем больше хлопот доставит это пользователям. Разработчик намерен свести к минимуму возникающие неудобства. Поразмыслив над имеющимися возможностями, он осознает, что если добавить дополнительное закрытое наследование класса Cricket от Grasshopper, то другие изменения в иерархии не потребуются. Программист радостно улыбается этой мысли, обрадованный перспективой большого выигрыша в функциональности за счет небольшого проигрыша в сложности.
Представьте себя на месте этого программиста и... удержитесь от соблазна.
Правило 44. Говорите то, что думаете, понимайте то, что говорите
Во введении к этому разделу, посвященному объектно-ориентированному программированию, я подчеркнул, насколько важно понимать, что означают различные объектно-ориентированные конструкции С++. Такое понимание во многом отличается от простого знания правил языка. Например, правила С++ говорят, что если класс D открыто наследует от класса В, то существует стандартное преобразование указателей D в указатели В; что открытые функции-члены класса В наследуются как открытые функции-члены класса D и т.д. Все это верно, но практически бесполезно, если вы стараетесь перевести ваш проект на язык С++. Вместо этого необходимо осознавать, что открытое наследование означает «есть разновидность», что если D открыто наследует от В, то каждый объект типа D является разновидностью объекта типа В. Таким образом, если при проектировании вы имеете в виду отношение «есть разновидность», то вам следует использовать открытое наследование.
Говорить то, что вы имеете в виду, - значит выиграть лишь половину сражения. Оборотная сторона медали, а именно понимание того, что вы говорите, не менее важна. Например, было бы безответственно, если не сказать аморально, наспех объявить функции класса невиртуальными, не осознавая, что при таком определении вы налагаете ограничения на производные классы. Объявляя невиртуальную функцию-член, вы в действительности утверждаете следующее: данная функция представляет собой инвариант относительно специализации; если этого не учитывать, последствия будут плачевными.
Эквивалентность открытого наследования и отношения «есть разновидность», а также эквивалентность невиртуальных функций-членов и инвариантности по отношению к специализации - это примеры, иллюстрирующие, насколько
194
Наследование и ООП
определенные конструкции С++ соответствуют идеям разработчика. Следующий список содержит наиболее важные из этих соответствий:
1. Наличие обшрго базового класса означает наличие общих свойств. Если класс Di и класс D2 объявляют класс В своим базовым классом, то Dl и D2 наследуют общие элементы данных и/или общие функции-члены В (см. правило 43).
2. Открытое наследование означает «есть разновидность». Если класс D открыто наследует от класса В, то каждый объект типа D также является объектом типа В, но не наоборот (см. правило 35).
3. Закрытое наследование означает «реализацию посредством». Если класс D закрыто наследует от класса В, объекты типа D достаточно просто реализуются с помощью объектов типа В; между объектами типов BhD нет концептуальной взаимосвязи (см. правило 42).
4. Вложение означает «содержит» или «реализуется посредством». Если класс А содержит элементы данных типа В, то объекты типа А либо имеют компонент типа В, либо реализуются посредством объектов типа В (см. правило 40).
Следующие соответствия применимы только тогда, когда речь идет об открытом наследовании:
1. Чистая виртуальность функции означает, что наследуется только интерфейс функции. Если класс С объявляет чисто виртуальную функцию-член mf, то подклассы С должны наследовать интерфейс mf и предоставить для нее свои собственные реализации (см. правило 36).
Предыдущая << 1 .. 81 82 83 84 85 86 < 87 > 88 89 90 91 92 93 .. 105 >> Следующая
Реклама
Авторские права © 2009 AdsNet. Все права защищены.
Rambler's Top100