Inheritance Is a Procedural Technique for Code Reuse

The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:

Мы все знаем, что наследование плохо и что композиция вместо наследования - это хорошая идея, но действительно ли мы понимаем, почему? Во всех статьях найденных мной, посвященных этой теме, авторы говорили, что наследование может быть вредным для вашего кода, поэтому лучше не использовать его. Эта “лучше” часть беспокоит меня; означает ли это, что иногда наследование имеет смысл? Несколько недель назад я брал интервью у Дэвида Уэста (автора книги Object Thinking, моей любимой книги об ООП), и он сказал, что наследование не должно существовать в объектно-ориентированном программировании (полное видео). Может быть, доктор Уэст прав и нам следует полностью забыть о ключевом слове extends в Java, например?

Я думаю, что мы должны. И я знаю, почему.

Это не потому, что мы вводим ненужную связность, как сказал Аллен Холуб в своей статье Why extends is evil. Он, безусловно, был прав, но я считаю, что это не корень проблемы.

“Наследовать”, как глагол в английском языке, имеет несколько значений. Вот это - то, что, по-моему, имели в виду создатели наследования в Simula: “Перенимать (качество, характеристику или предрасположение) генетически от своих родителей или предков”.

Перенимать характеристику от другого объекта - отличная идея, и это называется подтипизация. Она идеально вписывается в ООП и фактически позволяет полиморфизм: Объект класса Article наследует все характеристики объектов класса Manuscript и добавляет свои собственные. Например, он наследует возможность печати самого себя и добавляет возможность представить себя на конференцию:

interface Manuscript {
  void print(Console console);
}
interface Article extends Manuscript {
  void submit(Conference cnf);
}

Это субтипизация, и это отличная техника; когда требуется рукопись, мы можем предоставить статью, и никто не заметит ничего, потому что тип Статья является подтипом типа Рукопись (принцип подстановки Барбары Лисков).

Но что имеет общего копирование методов и атрибутов из родительского класса в дочерний с “производными характеристиками”? Реализация наследования именно в этом и заключается - копировании, и это никак не связано с значением слова “наследование”, которое я упомянул выше.

Реализация наследования намного ближе к другому значению: “Получать (деньги, имущество или титул) в качестве наследника после смерти предыдущего владельца.” Кого-то спрашиваете, кто умер? Объект считается умершим, если он позволяет другим объектам наследовать его инкапсулированный код и данные. Это реализация наследования.

class Manuscript {
  protected String body;
  void print(Console console) {
    console.println(this.body);
  }
}
class Article extends Manuscript {
  void submit(Conference cnf) {
    cnf.send(this.body);
  }
}

Класс Article копирует метод print() и атрибут body из класса Manuscript, как будто он не является живым организмом, а скорее мертвым, от которого мы можем наследовать его части, “деньги, собственность или титул”.

Наследование реализации было создано как механизм для повторного использования кода, и оно совсем не подходит для ООП. Да, на первый взгляд это может показаться удобным, но это абсолютно неправильно с точки зрения объектного мышления. Как и геттеры и сеттеры, наследование реализации превращает объекты в контейнеры с данными и процедурами. Конечно, удобно скопировать некоторые из этих данных и процедур в новый объект, чтобы избежать дублирования кода. Но в этом нет смысла объектов. Они не мертвы; они живые!

Не убивайте их наследованием!

Таким образом, я считаю, что наследование плохо, потому что это процедурная техника для повторного использования кода. Неудивительно, что это вносит все проблемы, о которых говорят уже много лет. Потому что это процедурно! Вот почему оно не подходит для объектно-ориентированного программирования.

Кстати, мы обсуждали эту проблему в нашем чате на Gitter (он уже мертв) на прошлой неделе, и тогда мне стало ясно, что именно не так с наследованием. Взгляните на наше обсуждение там.

Translated by ChatGPT gpt-3.5-turbo/36 on 2023-10-30 at 04:46

sixnines availability badge   GitHub stars