Ответ
Да, добавлять логику в геттер технически возможно и иногда оправданно, но это требует соблюдения важных принципов, чтобы не нарушить ожидания от метода доступа.
Принципы и лучшие практики:
-
Без побочных эффектов (No Side Effects): Геттер не должен изменять состояние объекта или внешнего мира. Его задача — только возвращать значение.
// ПЛОХО: Геттер с побочным эффектом public int getCounter() { this.count++; // Изменение состояния! return this.count; } -
Легковесность и быстродействие: Логика должна быть простой и быстрой. Избегайте в геттерах:
- Сложных вычислений.
- Обращений к базе данных или сети.
- Длительных операций ввода-вывода.
-
Предсказуемость и идемпотентность: Многократный вызов геттера с одними и теми же входными данными (состоянием объекта) должен возвращать одинаковый результат.
Допустимые примеры логики в геттере:
- Ленивая инициализация (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); // Возвращаем копию, а не оригинал }
Вывод: Логика в геттере допустима, если она соответствует принципам инкапсуляции, не имеет побочных эффектов и не вводит в заблуждение пользователя класса.