Самоинкапсуляция поля
Самоинкапсуляция отличается от обычной инкапсуляции поля тем, что рефакторинг производится над приватным полем.
Проблема
Вы используете прямой доступ к приватным полями внутри класса.
Решение
Создайте геттер и сеттер для поля, и пользуйтесь для доступа к полю только ими.
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;
}
}
Причины рефакторинга
Бывает так, что вам перестаёт хватать гибкости с прямым доступом к приватному полю внутри класса. Вы хотите иметь возможность инициализировать значение поля при первом запросе или производить какие-то операции над новыми значениями поля в момент присваивания, либо делать все это разными способами в подклассах.
Достоинства
-
Непрямой доступ к полям — это когда работа с полем происходит через методы доступа (геттеры и сеттеры). Этот подход отличается гораздо большей гибкостью, чем прямой доступ к полям.
-
Во-первых, вы можете осуществлять сложные операции при получении или установке данных в поле. Ленивая инициализация, валидация значений в поле — все это легко реализуемо внутри геттеров и сеттеров поля.
-
Во-вторых, что ещё важнее, вы можете переопределять геттеры и сеттеры в подклассах.
-
-
Вы можете вообще не реализовывать сеттер для поля. Значение поля будет задаваться только в конструкторе, делая это поле неизменяемым для всего периода жизни объекта.
Недостатки
- Когда используется прямой доступ к полям, код выглядит проще и нагляднее, хотя и теряет в гибкости.
Порядок рефакторинга
-
Создайте геттер (и опциональный сеттер) для поля. Они должны быть защищёнными (
protected
) либо публичными (public
). -
Найдите все прямые обращения к полю и замените их вызовами геттера и сеттера.