Можно ли добавлять логику в геттер (getter)?

«Можно ли добавлять логику в геттер (getter)?» — вопрос из категории ООП, который задают на 24% собеседований AQA / Automation. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

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

Принципы и лучшие практики:

  1. Без побочных эффектов (No Side Effects): Геттер не должен изменять состояние объекта или внешнего мира. Его задача — только возвращать значение.

    // ПЛОХО: Геттер с побочным эффектом
    public int getCounter() {
        this.count++; // Изменение состояния!
        return this.count;
    }
  2. Легковесность и быстродействие: Логика должна быть простой и быстрой. Избегайте в геттерах:

    • Сложных вычислений.
    • Обращений к базе данных или сети.
    • Длительных операций ввода-вывода.
  3. Предсказуемость и идемпотентность: Многократный вызов геттера с одними и теми же входными данными (состоянием объекта) должен возвращать одинаковый результат.

Допустимые примеры логики в геттере:

  • Ленивая инициализация (Lazy Initialization): Инициализация тяжелого поля только при первом обращении.
    private ExpensiveObject expensiveField;
    public ExpensiveObject getExpensiveField() {
        if (this.expensiveField == null) {
            this.expensiveField = loadFromDatabase(); // Допустимо, если выполняется один раз
        }
        return this.expensiveField;
    }
  • Вычисляемое свойство (Derived Property): Возврат значения, основанного на других полях объекта.
    public class User {
        private String firstName;
        private String lastName;
        public String getFullName() {
            return String.format("%s %s", firstName, lastName); // Легкая логика форматирования
        }
    }
  • Защита внутреннего состояния: Возврат защитной копии (defensive copy) изменяемого объекта.
    private List<String> internalList = new ArrayList<>();
    public List<String> getInternalList() {
        return new ArrayList<>(internalList); // Возвращаем копию, а не оригинал
    }

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