Что такое инкапсуляция?
Разберём популярный вопрос на собеседовании джуниор разработчика.
В 2013 году я отвечала, что инкапсуляция - это сокрытие деталей реализации. Обращаемся к объекту через методы и получаем ожидаемый результат, не погружаясь в лишние детали. Что там творится внутри метода - неважно.
Это верный ответ, но не полный.
Выделить часть кода в отдельный метод - это ещё не инкапсуляция. Такое можно провернуть в любом языке, это не делает его объекто-ориентированным.
❓Что же такое инкапсуляция?
У каждого объекта есть состояние - внутренние поля.
Иногда с ограничениями:
▪️Возраст - целое число меньше 120
▪️Имя - хотя бы одна буква
Иногда поля связаны между собой:
▪️Статус пользователя зависит от количества заказов
▪️Коэффициент ОСАГО зависит от города
Инкапсуляция - это когда состояние объекта нельзя поменять напрямую, только через методы класса. При этом важно защитить внутреннее состояние от нежелательных изменений. Это ответ на первый вопрос перед постом.
На практике решение обычно простое: сделать поля private и добавить методы get и set. Но иногда этого недостаточно.
❓Что не так с инкапсуляцией в классе Account?
Метод getOrders отдаёт список заказов List<Order>. Подразумевается, что клиент добавит ещё один заказ или обработает список.
По факту возможностей гораздо больше:
❌Удалить элементы
❌Отредактировать текущие заказы
В сложных системах не поможет комментарий "этот список только для добавления". Надёжный способ избежать ошибок - это понятный и ограниченный API.
Правильный ответ на вопрос 2:
Инкапсуляция так себе: внутреннее состояние (список заказов) не защищено.
Возможность создать два аккаунта с одним ID - вопрос дизайна и сценариев работы. С точки зрения инкапсуляции всё ок - ID нельзя поменять.
❓Как исправить ситуацию и защитить список заказов?
1️⃣ Хранить заказы отдельно
2️⃣ Поменять класс:
▫️Добавить orders модификатор final
▫️Добавить метод addOrder
▫️Метод getOrders пусть возвращает неизменяемый список
(возможны другие варианты, зависит от контекста)
#core
Post #193
5.14K
- ❤ 1