Возможно, сначала мы должны вспомнить, какова ценность самого наследования.Наследование - это механизм как повторного использования кода, так и повторного использования интерфейса (полиморфизм).Но вы можете повторно использовать код без наследования, используя состав и делегирование.И во многих языках вы можете иметь полиморфизм без наследования, но не во всех языках.В строго типизированном языке, таком как C ++, полиморфизм, который сам по себе является другим важным механизмом повторного использования кода, может быть достигнут только с помощью наследования.Фактически, C ++ различает публичное и частное наследование для интерфейса и повторного использования кода соответственно.Подробнее об этом позже.
Как правило, методы класса рассматриваются как создание контракта с клиентами этого класса: он гарантирует, что до тех пор, пока вы вызываете метод, удовлетворяющий определенным предварительным условиям, метод будет давать определенные результаты.«Правильное» наследование таково, что экземпляр подкласса можно заменить его родительским классом, не нарушая контракт родителя.То есть, ни один из методов подкласса не должен переопределять методы его базового класса, требующие более строгих предварительных условий или выдачи более «менее» результатов.Возвращаясь к C ++, поскольку существует четкое различие между публичным и частным наследованием, когда требуется первое, чтобы можно было заменить экземпляр подкласса на экземпляр базового класса, обычно считается "правильным", чтобы подстановка была семантически правильной.Иначе, почему бы не использовать частное наследование?
Является ли Ostrich
допустимым подклассом Bird
?Это зависит от того, какая у вас абстракция Bird
?Если у класса Bird
есть метод Bird::fly
, который делает что-то осязаемое, но Ostrich::fly
переопределяет это, чтобы вызвать исключение и, таким образом, обеспечивает "меньше", чем его базовый класс, я бы сказал, нет.Но если у класса Bird
не было метода fly
(есть другой подкласс Flying_Bird
, который имеет), нет проблем.
Мой ответ таков: то, что справедливо для C ++, не является плохим руководством дляобъектно-ориентированный язык.В таких языках, как Python, где иерархия наследования не требуется для полиморфизма, люди могут иметь большую склонность использовать наследование только для повторного использования кода.Если это повторное использование хорошо документировано, это может не быть проблемой.Но когда я вижу иерархию классов, я ожидаю, что подклассы потенциально будут использоваться полиморфно.