Что такое сеттер (setter) и какова его цель?

«Что такое сеттер (setter) и какова его цель?» — вопрос из категории Основы программирования, который задают на 10% собеседований QA Тестировщик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Сеттер (setter) — это публичный метод в объектно-ориентированном программировании, предназначенный для безопасного изменения значения приватного (private) или защищенного (protected) поля объекта.

Основные цели использования сеттеров:

  1. Инкапсуляция: Сокрытие внутреннего состояния объекта. Прямой доступ к полям заменяется контролируемыми методами.
  2. Валидация данных: Проверка нового значения на корректность перед его присвоением (например, диапазон, формат, бизнес-правила).
  3. Добавление побочной логики: Возможность выполнить дополнительные действия при изменении значения: логирование, уведомление наблюдателей, пересчет зависимых значений.
  4. Обеспечение согласованности: Поддержание инвариантов класса (например, если endDate должен быть позже startDate).

Пример на Java с валидацией:

public class BankAccount {
    private double balance;

    // Сеттер для баланса с валидацией
    public void setBalance(double newBalance) {
        if (newBalance < 0) {
            throw new IllegalArgumentException("Баланс не может быть отрицательным.");
        }
        // Логирование изменения
        System.out.println("Баланс изменен с " + this.balance + " на " + newBalance);
        this.balance = newBalance;
    }

    // Геттер для чтения значения
    public double getBalance() {
        return this.balance;
    }
}

// Использование
BankAccount account = new BankAccount();
account.setBalance(1000.0); // Корректно
// account.setBalance(-50); // Выбросит исключение

В современных языках сеттеры часто реализуются через свойства (properties) (C#, Python, Kotlin), которые выглядят как прямое присваивание, но под капотом вызывают метод-сеттер.

Пример свойства в Python:

class User:
    def __init__(self):
        self._age = 0  # Защищенный атрибут

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, value):
        if not (0 <= value <= 120):
            raise ValueError("Возраст должен быть от 0 до 120.")
        self._age = value

user = User()
user.age = 25  # Вызывает сеттер
# user.age = 150 # Вызовет ValueError