Является ли наследование конкретных классов злом?

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

Я видел аргументы против наследование и Я видел счетчик аргументы, но мне любопытно, что на самом деле делают другие поддерживающие базы больших кодов. Является ли страх раздутым? Наследуете ли вы от конкретных классов или скептики наследования правильны? Мне особенно интересно услышать от тех людей, которые работают на С++.

Ответ 1

Не парень С++ (у вас есть профессиональный опыт работы с крупными корпоративными системами в С#, java и ruby), но вот мои 2 цента в любом случае

Это не черное и белое.

Проблема с наследованием заключается в том, что она вводит жесткую связь. Хуже того, эта связь обычно происходит вокруг инкапсулированного состояния. Изменения в суперклассах могут влиять на иерархические иерархии наследования, создавая тонкие и трудно прогнозируемые ошибки.

Сегрегация интерфейса полностью оборачивает эти проблемы, поскольку она не нарушает инкапсуляцию тем же способом.

Хорошая вещь о наследовании заключается в том, что иногда у вас есть объектная модель, которая на самом деле то же самое, просто с очень небольшим изменением или добавлением. До тех пор, пока это изменение будет очень ясным, не охваченным широким охватом и не является дополнительным ограничением (см. Проблему circle-ellipse) повторное использование кода превзойдет тугое соединение.

Я придерживаюсь композиции над наследованием как правило, а не закона.

Ответ 2

Вы можете частным образом получить конкретные классы. Частное наследование не требует замены Liskov; это, по сути, просто удобный способ "смешать" функциональность класса.

Наше наследование, с другой стороны, требует замены Лискова. Таким образом, обычно публичное наследование от конкретных классов является плохим, если только такой класс не предназначен для использования в качестве базового класса (многие из них не являются).

Ответ 3

Хорошая конструкция предусматривает, что конкретные классы должны делать одну, относительно небольшую вещь хорошо и эффективно. В частности, в С++ конкретные классы подчеркивают их сходство с конкретными типами, такими как int и char, часто при перегрузке оператора и имея только не виртуальные функции. Поскольку конкретные классы не предназначены для отображения полиморфного поведения, они не должны наследоваться. Также см. Раздел 25.2 Язык программирования С++ для получения дополнительной информации о правильном использовании конкретных типов на этом языке.