Также известен как Pull Up Constructor Body

Рефакторинг Подъём тела конструктора

Проблема

Подклассы имеют конструкторы с преимущественно одинаковым кодом.

Решение

Создайте конструктор в суперклассе и вынесите в него общий для подклассов код. Вызывайте конструктор суперкласса в конструкторах подкласса.
До
class Manager extends Employee {
  public Manager(String name, String id, int grade) {
    this.name = name;
    this.id = id;
    this.grade = grade;
  }
  //...
}
После
class Manager extends Employee {
  public Manager(String name, String id, int grade) {
    super(name, id);
    this.grade = grade;
  }
  //...
}
До
public class Manager: Employee 
{
  public Manager(string name, string id, int grade) 
  {
    this.name = name;
    this.id = id;
    this.grade = grade;
  }
  //...
}
После
public class Manager: Employee 
{
  public Manager(string name, string id, int grade): base(name, id)
  {
    this.grade = grade;
  }
  //...
}
До
class Manager extends Employee {
  public __construct($name, $id, $grade) {
    $this->name = $name;
    $this->id = $id;
    $this->grade = $grade;
  }
  ...
}
После
class Manager extends Employee {
  public __construct($name, $id, $grade) {
    parent::__construct($name, $id);
    $this->grade = $grade;
  }
  ...
}
До
class Manager(Employee):
    def __init__(self, name, id, grade):
        self.name = name
        self.id = id
        self.grade = grade
    #...
После
class Manager(Employee):
    def __init__(self, name, id, grade):
        Employee.__init__(name, id)
        self.grade = grade
    #...

Причины рефакторинга

Чем этот рефакторинг отличается от подъёма метода?

  1. В Java подклассы не могут наследовать конструктор, поэтому вы не можете просто применить подъём метода к конструктору подкласса и удалить его после перемещения всего кода конструктора в суперкласс. Вдобавок к созданию конструктора в суперклассе нужно будет иметь конструкторы в подклассах с простым делегированием к конструктору суперкласса.

  2. В C++ и Java (в случае, если вы явно не вызвали конструктор суперкласса) конструктор суперкласса автоматически вызывается перед конструктором подкласса, что делает обязательным перемещение общего кода только из начала конструкторов подклассов (т.к. вы не сможете вызвать конструктор суперкласса в произвольном месте конструктора подкласса).

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

Порядок рефакторинга

  1. Создайте конструктор в суперклассе.

  2. Извлеките общий код из начала конструктора каждого из подклассов в конструктор суперкласса. Перед этим действием стоит попробовать поместить как можно больше общего кода в начало конструктора.

  3. Поместите вызов конструктора суперкласса первой строкой в конструкторах подклассов.

Устали читать?

Сбегайте за подушкой, у нас тут контента на 7 часов чтения.

Или попробуйте наш новый интерактивный курс по рефакторингу. Он более информативный и гораздо более интересный, чем банальный текст.

Узнать больше...

Живой пример

Первый раз здесь? Ничего страшного!

У нас здесь всё просто – интерактивный пример очень похож на видео (но выглядит гораздо круче).

  1. После начала проигрывания, вам показываются разнообразные подсказки и сообщения. Вы продвигаетесь дальше, кликая на них.
  2. Вы можете перематывать шаги, используя стрелки слева.
  3. Кроме того, вы можете посмотреть разницу между первоначальным и получившимся кодом, нажав кнопку с глазом ().
  4. Кнопка компиляции () позвоялет проверить текущий код на наличие ошибок.