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

 

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

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

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

class Airport {...}; Il Представляет аэропорты.
class Airplane {
public:
virtual void fly(const Airports destination);
};
void Airplane:: fly(const Airports destination) {
код no умолчанию для полета самолета
в заданный пункт назначения - destination
}
class ModelA: public Airplane { ... } ; class ModelB: public Airplane { ... } ,-
Чтобы засвидетельствовать, что все самолеты должны поддерживать функцию fly, и для того, чтобы отразить тот факт, что различные модели могут в принципе требовать различных реализаций для fly, функция Airplane: : f Iy определена как
ModelA и ModelB в качестве стандартного поведения используется тело функции Airplane: : fly, которую наследуют как ModelA, так и ModelB.
Это классический пример объектно-ориентированного проектирования. Два класса имеют общие свойства (способ реализации fly), и, как следствие, общее свойство реализуется в базовом классе и наследуется обоими классами. Благодаря этому проект явным образом выделяет общие свойства, избегает дублирования кода, благоприятствует проведению будущих модернизаций, облегчает долгосрочную эксплуатацию - иными словами, обеспечивает все то, за что так ценится объектно-ориентированная технология. Программисты компании XYZ Airlines могут собой гордиться.
Теперь предположим, что дела XYZ идут в гору, и фирма решает приобрести новый самолет модели С. Модель С отличается от моделей А и В, например, тем, что летает по-другому.
Программисты компании XYZ добавляют к иерархии класс для модели с, но в спешке забывают переопределить функцию fly:
class ModelC: public Airplane {
Назревает катастрофа: делается попытка летать на объекте Modele так, как если бы это был объект ModelA или ModelB. Такой образ действий вряд ли может внушить доверие пассажирам.
Проблема здесь заключается не в том, что Airplane: : f Iy ведет себя определенным образом по умолчанию, а в том, что такое наследование допускает неявное применение данной функции для Modele. К счастью, легко можно предложить подклассам поведение по умолчанию, но не предоставлять им его, если они сами об этом не попросят. Весь фокус состоит в том, чтобы разделить интерфейс виртуальной функции и ее реализацию по умолчанию. Вот один из способов, который позволяет добиться этого:
class Airplane { public:
virtual void fly(const Airports destination) = 0; protected:
void defaultFly(const Airports destination);
};
void Airplane::defaultFly(const Airports destination) {
код no умолчанию для полета самолета
в заданный пункт назначения - destination

// Функция fly не объявлена.
};
Далее они делают что-нибудь в таком роде:
Airport JFK{...); // Аэропор
Airplane *ра = new ModelC;
// Аэропорт Джона Кеннеди в Нью-Йорке,
pa->fIy(JFK);
// Вызов Airplane:: fly!
Правило 36 . El
I
ЩШ^ Обратите внимание, что функция Airplane: : f Iy была преобразована в чис-^^^шю виртуальную функцию. Это обеспечивает интерфейс для полета. В классе ^^¦irplane присутствует и реализация по умолчанию, но теперь она представлена ^^^в форме независимой функции, def aultFly. Классы, подобные ModelA и ModelB, I которые хотят использовать поведение по умолчанию, просто применяют встраива-I емый вызов defaultFly внутри fly (см. также информацию о взаимодействии I встраиваемости и виртуальности функций в правиле 33):
class ModelA: public Airplane { public:
virtual void fly(const Airport& destination) { defaultFly(destination); }
};
class ModelB: public Airplane { public:
virtual void fly(const Airport& destination) { defaultFly(destination) ; }
t
Теперь для класса Modele возможность случайного наследования некорректной реализации fly исключена, поскольку чисто виртуальная функция в Airplane ^^!вынуждаег Modele создавать свою собственную версию fly.
P
};
class Modele: public Airplane { public:
virtual void fly(const Airports destination);
};
void Modele:: fly(const Airport& destination) {
код для полета самолета типа Modele в заданный пункт назначения }
Эта схема не обеспечивает «защиту от дурака» (программисты все же могут создать себе проблемы копированием/вставкой), но она более надежна, чем исходная. Что же касается функции Airplane: :defaultFly, то она защищена, поскольку действительно является деталью реализации Airplane и его производных классов. Пассажиры теперь должны быть обеспокоены только тем, чтобы Улететь, а не тем, как происходит полет.
Также важно, что Airplane: :defaultFly объявлена как невиртуальная Функция. Это связано с тем, что никакой подкласс не должен ее перегружать -обстоятельство, которому посвящено правило 37. Если бы defaultFly была виртуальной, перед вами снова встала бы та же самая проблема: что, если некоторые Подклассы «забудут» переопределить defaultFly должным образом?
Иногда высказываются возражения против идеи разделения функций на обеспечивающие интерфейс и обеспечивающие реализацию по умолчанию, такие, например, как fly и defaultFly. Прежде всего, отмечают программисты, это засоряет пространство имен класса близкими названиями функций. Все же они
Предыдущая << 1 .. 63 64 65 66 67 68 < 69 > 70 71 72 73 74 75 .. 105 >> Следующая
Реклама
Авторские права © 2009 AdsNet. Все права защищены.
Rambler's Top100