Принципы объектно-ориентированного программирования

         

Что такое "правильное" наследование



Что такое "правильное" наследование

Важнейшую проблему "правильного" наследования я начну с термина замещаемость (substitutability), взятого у Маршалла Клайна (Marshall Cline) и Грега Ломау (Greg Lomow) (C++ FAQs, Addison-Wesley, 1998). Этот термин означает, что поведение производного класса достигается путем замещения поведения, заимствованного у базового класса. Это одно из важнейших правил, которое вам нужно соблюдать при построении работающей иерархии классов. (Под "работающими" я подразумеваю системы, выдержавшие проверку временем и оправдавшие надежды на повторное использование и расширение кода.)

А вот еще одно важное правило, которому я советую следовать при создании собственной иерархии классов: любой унаследованный интерфейс производного класса не должен требовать больше и обещать меньше, чем в базовом классе. Пренебрежение этим правилом приводит к разрушению существующего кода. Интерфейс класса — это контракт между классом и пользователями, применяющими этот класс. Имея ссылку на производный класс, программист всегда может обращаться с ним, как с базовым классом. Это называется восходящим преобразованием типа (upcasting). В нашем примере клиент, имея ссылку на объект ContractEmp-loyee,


обладает и неявной ссылкой на его базовый класс — объект Employee. Поэтому согласно определению объект ContractEmployee всегда должен поддерживать выполнение функций своего базового класса. Заметьте: это правило распространяется только на функциональные возможности базового класса. В производный класс можно добавить и другие функции, которые выполняют и более узкие (или более широкие) задачи, чем унаследованные функции. Поэтому данное правило применяется только к унаследованным членам, поскольку существующий код рассчитан на работу только с этими членами.



Содержание раздела