Глянь мой новый курс по Git! Привет! Глянь мой новый курс по Git! Привет! Глянь мой новый курс по Git на GitByBit.com! Привет! Хочешь круто подтянуть Git? Глянь мой новый курс на GitByBit.com!

Самоинкапсуляция поля

Также известен как: Self Encapsulate Field

Самоинкапсуляция отличается от обычной инкапсуляции поля тем, что рефакторинг производится над приватным полем.

Проблема

Вы используете прямой доступ к приватным полями внутри класса.

Решение

Создайте геттер и сеттер для поля, и пользуйтесь для доступа к полю только ими.

До
class Range {
  private int low, high;
  boolean includes(int arg) {
    return arg >= low && arg <= high;
  }
}
После
class Range {
  private int low, high;
  boolean includes(int arg) {
    return arg >= getLow() && arg <= getHigh();
  }
  int getLow() {
    return low;
  }
  int getHigh() {
    return high;
  }
}
До
class Range 
{
  private int low, high;
  
  bool Includes(int arg) 
  {
    return arg >= low && arg <= high;
  }
}
После
class Range 
{
  private int low, high;
  
  int Low {
    get { return low; }
  }
  int High {
    get { return high; }
  }
  
  bool Includes(int arg) 
  {
    return arg >= Low && arg <= High;
  }
}
До
private $low;
private $high;

function includes($arg) {
  return $arg >= $this->low && $arg <= $this->high;
}
После
private $low;
private $high;

function includes($arg) {
  return $arg >= $this->getLow() && $arg <= $this->getHigh();
}
function getLow() {
  return $this->low;
}
function getHigh() {
  return $this->high;
}
До
class Range {
  private low: number
  private high: number;
  includes(arg: number): boolean {
    return arg >= low && arg <= high;
  }
}
После
class Range {
  private low: number
  private high: number;
  includes(arg: number): boolean {
    return arg >= getLow() && arg <= getHigh();
  }
  getLow(): number {
    return low;
  }
  getHigh(): number {
    return high;
  }
}

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

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

Достоинства

  • Непрямой доступ к полям — это когда работа с полем происходит через методы доступа (геттеры и сеттеры). Этот подход отличается гораздо большей гибкостью, чем прямой доступ к полям.

    • Во-первых, вы можете осуществлять сложные операции при получении или установке данных в поле. Ленивая инициализация, валидация значений в поле — все это легко реализуемо внутри геттеров и сеттеров поля.

    • Во-вторых, что ещё важнее, вы можете переопределять геттеры и сеттеры в подклассах.

  • Вы можете вообще не реализовывать сеттер для поля. Значение поля будет задаваться только в конструкторе, делая это поле неизменяемым для всего периода жизни объекта.

Недостатки

  • Когда используется прямой доступ к полям, код выглядит проще и нагляднее, хотя и теряет в гибкости.

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

  1. Создайте геттер (и опциональный сеттер) для поля. Они должны быть защищёнными (protected) либо публичными (public).

  2. Найдите все прямые обращения к полю и замените их вызовами геттера и сеттера.