"Ну и что? — скажете вы. — Такое наследование работает и сохраняет нам силы и время". Это, конечно, так, но мои предупреждения — это не просто сотрясание воздуха. Такие искажения запутывают программиста уже и сейчас, но ещё больше будут мешать в дальнейшем. Однажды программист, не знакомый с нашими "приёмчиками", будет читать нашу программу, пытаясь понять, что же она делает. Вводящие в заблуждение представления очень трудны для понимания и ведения программы.
_________________
250 стр. Часть 4. Наследование

Рис. 22.2. Класс Savings реализован как подкласс checking
Кроме того, такие искажения могут привести к проблемам в будущем. Например, представьте себе, что банк изменит свою политику относительно чековых счетов. Скажем, он решит взимать гонорар за обслуживание чековых счетов только в том случае, если минимальный баланс упадёт ниже некоторого значения в течение месяца.
Такое изменение политики банка можно легко отразить в классе Checking . Все, что нужно сделать, — это добавить новый член в класс Checking , чтобы следить за минимальным балансом в течение месяца. Назовём его minimumBalance .
Однако теперь возникает проблема. Если Savings наследует Checking , значит, Savings тоже получает этот член. При этом он не используется, поскольку в сберегательных счетах минимальный баланс не нужен. Так что дополнительный член просто присутствует в классе. Итак, каждый объект чекового счёта имеет дополнительный член minimumBalance . Один дополнительный член — это не так уж и много, но он вносит свою лепту в общую неразбериху.
Такие изменения имеют свойство накапливаться. Сегодня это один член, а завтра — изменённая функция-член. В результате объекты класса Savings будут содержать множество дополнительных данных, которые нужны исключительно в классе Checking . Если вы будете невнимательны, изменения в классе Checking могут перейти к классу Savings и привести к его некорректной работе.
Далее банк решил изменить правила работы с чековыми счетами. Для этого вам требуется изменить некоторые функции в Checking . Эти изменения автоматически перейдут в подклассы. Предположим, например, что банк решил начислять дополнительные проценты по чековым вкладам ( ну, бывают же чудеса... ) — но главное чудо будет в том, что при нашей системе наследования эти же проценты будут начисляться и на сберегательных счетах.
Как же этого избежать? Если поменять местами Checking и Savings , проблема не исчезнет. Нужен некий третий класс ( назовём его Account ), который будет воплощать в себе всё то общее, что есть у Checking и Savings . Такая связь приведена на рис. 22.3.
Каким образом создание нового класса Account решит наши проблемы? Во-первых, такой класс сделает более аккуратным описание реального мира ( чем бы он ни являлся ). В нашей концепции мира ( по крайней мере, в моей ) действительно есть нечто, что можно назвать счётом.
_________________
251 стр. Глава 22. Разложение классов
Сберегательные и чековые счета являются частным случаем этой более фундаментальной концепции.
Кроме того, класс Savings отмежёвывается от изменений в классе Checking ( и наоборот ). Если банк решит провести фундаментальные изменения во всех счетах, можно просто изменить класс Account , и все подклассы автоматически унаследуют эти изменения. Но если банк изменит политику только для чековых счетов, можно просто модифицировать класс Checking , не изменяя при этом класс Savings .
Такая процедура отбора общих свойств похожих классов и называется разложением. Этот процесс очень важен в объектно-ориентированных языках по причинам, которые были приведены выше, а также потому, что разложение помогает избавиться от избыточности. Позвольте мне повториться: избыточность — это не просто плохо, это очень плохо...

Рис. 22.3. Классы checking и Savings , базирующиеся на классе Account

«Разложение будет обоснованным только в том случае, когда взаимосвязь, представляемая наследованием, соответствует реальности. Выделение общих свойств классаMouse иJoystick и разложение их на "множители" вполне допустимо. И мышь и джойстик являются аппаратными устройствами позиционирования. Но выделение общих свойств классовMouse иDisplay ничем не обосновано.»
Читать дальше