Правильное наследование - PullRequest
       27

Правильное наследование

2 голосов
/ 02 августа 2010

Что подразумевается под правильным наследованием?

Ответы [ 4 ]

4 голосов
/ 02 августа 2010

Эта тема дает хорошее резюме:

  • Правильное наследование происходит, когда производный класс «IS A» специализированный тип базового класса. Пример Cat IS A Animal.

  • Неправильное наследование происходит, когда класс наследуется просто для повторного использования кода без каких-либо других отношений. Пример Cat наследуется от двигателя. Cat - это не двигатель, но и двигатель, и мурлыканье.

3 голосов
/ 03 августа 2010

Я хотел бы добавить к тому, что сказали Джастин и Бакстер.

Термин «правильное наследование» не совсем определен.Правильное использование наследования - довольно субъективная проблема ...

Рассмотрим следующий пример:

  • Интерфейс: Bird
  • Конкретный класс: Ostrich

Должен ли Ostrich наследоваться от Bird?С зоологической точки зрения это имеет смысл, но с точки зрения компьютерных наук ... не так много.Если у Bird есть метод fly, то как мне справиться с этим в Ostrich::fly: x?

В сообществе CS идет какая-то война.Действительно, вы регулярно будете видеть книги, где Circle наследуется от Ellipse (или наоборот), когда это не имеет смысла с точки зрения CS.

Итак, мое собственное небольшое определение:

Учитывая, что интерфейс определяет точную семантику для каждого из своих методов, конкретный класс должен наследовать от интерфейса только в том случае, если реализация каждого из методов соответствует указанной семантике.

0 голосов
/ 02 мая 2016

Возможно, сначала мы должны вспомнить, какова ценность самого наследования.Наследование - это механизм как повторного использования кода, так и повторного использования интерфейса (полиморфизм).Но вы можете повторно использовать код без наследования, используя состав и делегирование.И во многих языках вы можете иметь полиморфизм без наследования, но не во всех языках.В строго типизированном языке, таком как C ++, полиморфизм, который сам по себе является другим важным механизмом повторного использования кода, может быть достигнут только с помощью наследования.Фактически, C ++ различает публичное и частное наследование для интерфейса и повторного использования кода соответственно.Подробнее об этом позже.

Как правило, методы класса рассматриваются как создание контракта с клиентами этого класса: он гарантирует, что до тех пор, пока вы вызываете метод, удовлетворяющий определенным предварительным условиям, метод будет давать определенные результаты.«Правильное» наследование таково, что экземпляр подкласса можно заменить его родительским классом, не нарушая контракт родителя.То есть, ни один из методов подкласса не должен переопределять методы его базового класса, требующие более строгих предварительных условий или выдачи более «менее» результатов.Возвращаясь к C ++, поскольку существует четкое различие между публичным и частным наследованием, когда требуется первое, чтобы можно было заменить экземпляр подкласса на экземпляр базового класса, обычно считается "правильным", чтобы подстановка была семантически правильной.Иначе, почему бы не использовать частное наследование?

Является ли Ostrich допустимым подклассом Bird?Это зависит от того, какая у вас абстракция Bird?Если у класса Bird есть метод Bird::fly, который делает что-то осязаемое, но Ostrich::fly переопределяет это, чтобы вызвать исключение и, таким образом, обеспечивает "меньше", чем его базовый класс, я бы сказал, нет.Но если у класса Bird не было метода fly (есть другой подкласс Flying_Bird, который имеет), нет проблем.

Мой ответ таков: то, что справедливо для C ++, не является плохим руководством дляобъектно-ориентированный язык.В таких языках, как Python, где иерархия наследования не требуется для полиморфизма, люди могут иметь большую склонность использовать наследование только для повторного использования кода.Если это повторное использование хорошо документировано, это может не быть проблемой.Но когда я вижу иерархию классов, я ожидаю, что подклассы потенциально будут использоваться полиморфно.

0 голосов
/ 02 августа 2010

Когда наследование соответствует отношениям IS A, в отличие от наследования исключительно для повторного использования кода без логического подчинения дочернего элемента суперклассом.

...