Я знаю, что вопрос обсуждался ранее , но, похоже, всегда предполагается, что наследование по крайней мере иногда предпочтительнее композиции. Я хотел бы оспаривать это предположение в надежде получить некоторое понимание.
Мой вопрос заключается в следующем: поскольку вы можете выполнить что-либо с композицией объекта, которую вы можете с классическим наследованием, и поскольку классическое наследование очень часто злоупотребляют [1], и поскольку состав объектов дает вам гибкость для изменения времени выполнения объекта делегата, почему бы вы никогда не использовали классическое наследование?
Я могу понять, почему вы рекомендуете наследование на некоторых языках, таких как Java и С++, которые не предлагают удобный синтаксис для делегирования. На этих языках вы можете сэкономить много ввода, используя наследование, когда это явно не так. Но другие языки, такие как Objective C и Ruby, предлагают как классическое наследование, так и очень удобный синтаксис для делегирования. Я знаю, что язык программирования Go является единственным языком, который, насколько мне известно, решил, что классическое наследование больше проблем, чем того стоит, и поддерживает только делегирование для повторного использования кода.
Еще один способ изложить мой вопрос таков: даже если вы знаете, что классическое наследование не является неправильным для реализации определенной модели, является ли эта причина достаточной для ее использования вместо композиции?
[1] Многие люди используют классическое наследование для достижения полиморфизма вместо того, чтобы позволить своим классам реализовывать интерфейс. Цель наследования - повторное использование кода, а не полиморфизм. Кроме того, некоторые люди используют наследование, чтобы моделировать их интуитивное понимание отношения "is-a" которое часто может быть проблематичным.
Обновление
Я просто хочу уточнить, что я имею в виду, когда говорю о наследовании:
Я говорю о вид наследования, при котором класс наследуется от частично или полностью реализованного базового класса. Я не говорю о наследовании от чисто абстрактного базового класса, который составляет то же самое, что реализация интерфейса, к которому я для записи не спорю.
Обновление 2
Я понимаю, что наследование - единственный способ добиться полиморфизма я С++. В этом случае очевидно, почему вы должны его использовать. Поэтому мой вопрос ограничен такими языками, как Java или Ruby, которые предлагают различные способы достижения полиморфизма (интерфейсы и утиная типизация, соответственно).