Свёртывание иерархии
Проблема
У вас есть некая иерархия классов, в которой подкласс мало чем отличается от суперкласса.
Решение
Слейте подкласс и суперкласс воедино.
![Collapse Hierarchy - Before](/images/refactoring/diagrams/Collapse Hierarchy - Before.png?id=e95d97b3a9d564fbdba5ec0b76748f88)
![Collapse Hierarchy - After](/images/refactoring/diagrams/Collapse Hierarchy - After.png?id=db86997e7b68eaac829168048cd02a8b)
Причины рефакторинга
Развитие программы привело к тому, что подкласс и суперкласс стали очень мало отличаться друг от друга. Какая-то фича была убрана из подкласса, какой-то метод «переехал» в суперкласс, и вот вы уже имеете два практически одинаковых класса.
Достоинства
-
Уменьшается сложность программы. Меньше классов, меньше вещей, которые нужно держать в голове, меньше «движущихся частей», меньше вероятность сломать что-то при последующих изменениях в коде.
-
Навигация по коду становится проще, когда методы определены только в одном классе. Нужный метод не приходится искать по всей иерархии.
Когда нельзя применить
-
Если в иерархии классов находится больше одного подкласса, то после проведения рефакторинга, оставшиеся подклассы должны стать наследниками класса, в котором была объединена иерархия.
-
Однако имейте в виду, что это может привести к нарушению принципа подстановки Барбары Лисков. Например, если в программе эмуляторе городского транспорта неверно свернуть суперкласс
Транспорт
в подклассАвтомобиль
, классСамолёт
может оказаться наследникомАвтомобиля
, а это уже неправильно.
Порядок рефакторинга
-
Выберите, какой класс убрать удобнее: суперкласс или подкласс.
-
Используйте подъём поля и подъём метода, если вы решили избавиться от подкласса. Используйте спуск поля и спуск метода, если убран будет суперкласс.
-
Замените все использования класса, который будет удалён, классом, в который переезжают поля и методы. Зачастую это будет код создания классов, указания типов параметров и переменных, а также документации в комментариях.
-
Удалите пустой класс.