Зачем нужна инкапсуляция в ООП?



@IWantToBelievee

Я прочитал много статей и посмотрел еще больше роликов по ООП, но не могу понять, зачем нужна инкапсуляция. Объясняют везде примерно одинаково. Например, на одном канале человек привел в пример класс Database, и URL, который нельзя менять. Ну допустим, сделал я класс Database, начал добавлять туда какие-то URL, но кто сможет потом их поменять, если я не добавлю функцию для изменения? Какая разница, private я установил или public, функции для изменения не будет у программы и никто и никак не сможет поменять этот URL. Я не могу начать что-то использовать, пока не пойму, зачем конкретно это нужно. Все эти примеры — пустышки.


Решения вопроса 0


Ответы на вопрос 8



@AlexNest

Да начнется холивар
Видел кучу разных, зачастую противоположных, мнений, но на мой взгляд — инкапсуляция не равно сокрытие (про которое вы и пишите, судя по типам полей).
Сокрытие является частным случаем инкапсуляции. В общем же случае инкапсуляция подразумевает объединение связанных элементов в один объект. Например есть юзер. У него есть разные свойства (логин-пароль/аватарка/id-шка). И если данные можно хранить в структурах (словари/массивы/списки и т.д,), то функции, описывающие взаимодействие с этим юзером просто так не сгруппируешь. Для этого и придумали инкапсуляцию и ООП.
Сокрытие же в этом случае может применяться например для создания «точки входа» при работе с паролем для защиты от «дураков»/предварительной обработки/проверки данных.
Делаем поле private и все, «тупо изменить» его извне уже нельзя. Для его изменения мы предоставляем метод, который перед тем как изменить его (условно):

  • Валидирует значения по заданным критериям
  • Проверяет наличие прав на изменение пароля

UPD.

но кто сможет потом их поменять, если я не добавлю функцию для изменения?

Ну, видимо никто. Если не добавите советующую функцию.

Какая разница, private я установил или public, функции для изменения не будет у программы и никто и никак не сможет поменять этот URL.

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



@firedragon

Зайдите в гараж. В одном углу сварочник и электроды , в другом верстак, там сверлилка и коробки со свёрлами, дальше коробка с метизами. Все упорядочено и не нужно далеко ходить. Это будет инкапсуляция. В другом все свалено вместе и метизы и свёрла и отвертки и ножовки. Прежде чем начать работу вы ищете инструменты и детали



@delphinpro

Инкапсуляция — это грубо говоря объединение связанного функционала. В ООП в виде класса.
Плюс скрытие деталей реализации функциональности.

Если говорить о ваших классах Database и URL, то в первом объединяются функции работы с базой, а во втором с адресами. Это первое.
Второе: Классы имеют публичный интерфейс. Работая с классом через этот интерфейс, вам не нужно знать что происходит внутри. Достаточно знать, что дать на вход, и что вы получите на выходе.



@Starina_js

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

Полиморфизм, инкапсуляция, шаблоны проектирования (и т.п.) придумали для простой и банальной цели — удобство командной работы. Чтобы программисты быстрее закрывали задачи, чтобы быстрее понимали друг друга и чужой код, чтобы была стандартизация в командной работе, чтобы была определенная договоренность делать так, а не иначе. Конечно, не забываем учитывать бизнес задачи — экономия на реализацию и поддержку проекта, когда он разрастается.

Когда на проекте работают сотни программистов, хочешь ты или нет, будет создаваться система контрактов или договоренностей между людьми. Одна из таких — безопасность от случайных воздействий или устойчивость. Возможность скрыть или защитить данные от внешних воздействий. Хотя это не только, еще про объединение данных и функций работы с данными.

Пример: создали класс, в классе добавили свойство. Свойство используется в функциях этого класса и от него зависит поведение. Допустим какой-то коэффициент. Когда ты один работаешь на проекте, ты знаешь код и работаешь с этим свойством правильно, а вот когда работают сотни программистов, они понятия не имеют что это за свойство и не должны знать об этом. Кто-то может по ошибке перезаписать коэффициент и будет проблема…

Пример: бизнес торопиться вывести новую функцию на рынок. Чем быстрее выведет, тем быстрее начнет зарабатывать. Бизнес просит программистов делать это побыстрее. Программисты пыхтят, у них высокая нагрузка им некогда разбираться с чужим кодом. Видят нужное им свойство, начинают с ним работать и изменяют под себя.
Вроде все ок, и программа не упала и все тесты прошли, начали релизить проект. Прошла неделя и пользователь как-то нестандартно использовал новую функциональность и вместо 100 руб, списался 1 миллион. Беда косяк, а бывают и серьезней последствия. Случилось это потому, что кто-то изменил маленькое свойство в чужом коде.

Поэтому программисты решили договориться — объединяйте и важное прячьте, делайте недоступными для воздействия, хотите поменять коэф — давайте правильный и безопасный метод.

Кстати инкапсуляция это не только «про» или даже «в» ООП, оно вполне себе реализуется и в функциональном программировании.

Как-то так)



@Adamos

Инкапсуляция действительно защищает — мозг программиста от переполнения. И только.
Машинный код после компиляции класса, в котором методы и члены объявлены private или public — один и тот же.
Они нужны только для автоматической проверки компилятором — не ошибся ли программист.
А инкапсуляция — это не столько собирание в одну кучу того, что работает вместе, сколько обрывание любых связей с остальным кодом. За исключением реально необходимых. После чего класс становится вещью в себе, и вам можно работать с ним, не задумываясь о прочем коде, и работать с прочим кодом, не думая о потрохах этого класса.



@DollyPapper

Инкапсуляция вообще является (ИМХО) главным принципом из 4. Инкапсуляция + абстракция. Вы не поняли её основную идею. Инкапсуляция это объдинение в одной сущности данных (не обязательно в общем-то) и действий которая эта сущность может предоставить. Инкапсуляция + абстракция представляю собой в общем более общий принцип — сокрытие информации/сложности, и один без другого не сильно то полезен. Не путать с модификаторами доступа (public, private и тд). Этот принцип идет скрозь всю историю развития языков программирования и собственно является главной движущей силой их развития. Вот пример из реальной жизни: есть у вас микроволновка. Она имеет +- 2 нопки: выставить время, выставить мощность. Это интерфейс микроволновки, который доступен конечному пользователю. Всё что вам нужно знать, чтобы приготовить себе похавать — 1)на какой мощности это хавать, нужно готовить 2) сколько это нужно делать по времени. При этом очевидно внутри микроволновки происходит та самая сложность, микросхемы гоняют электрический ток, магнетрон изучает электромагнитные волны, всякая разная физика происходит и вот это вот всё. Итого: вся эти физика и электротехника инкапсулирована в объект микроволновки (инкапсулирована так, что мы не можем добраться до её внутреннего устройства, это важно. Т.е. мы не можем сами соединить проводки, поменять электрическую цель, чтобы себе похавать сделать, разработчик этой электропечки не дал нам даже потенциальную возможность это сделать легально. Можно конечно разобрать устройство и проделать все эти манипуляции, но это уже это на совести того самоделкина, кто это делает). Итого: мы имеем интерфейс из двух кнопок и получаем от обьекта микроволновки услугу — приготовить пожрать. Как там внутри это реализовано, нам не важно. Это и есть инкапсуляция + абстракция = сокрытие информации/сложности.
Более программистский пример: есть такая структура данных — Стек. Хотя по факту это не структура данных, а абстрактный тип данных. Советую этот термин загуглить, это важная составляющая в понимании ООП.
Представим, что стек это такой обьект который предоставляет услуги, по типу как мы представляли себе обьект микроволновки. Что нам нужно знать про стек, чтобы им пользоваться? Публичный интерфейс. Т.е. есть класс Stack с публичными методами push(), pop(), viewTopStack() (посмотреть первый элемент стека, без его удаление из самого стека). Всё, можно пользоваться. Как он внутри эти элементы хранит, простой ли это массив, или связный список, на сколько эффективно он там внутри работает — нам не важно. Это важно тому, кто предоставил нам в пользование данный класс. Мы знаем, что вызвав viewTopStack мы посмотрим первый элемент стека, вызвав push — положим что-то в стек, вызвав pop получим первый элемент, удалив его из стека (по аналогии: мы знаем что чтобы притоговить пожрать, нужно выставить в микроволновке время и мощность, на выходе получив наше адово хрючево). Если подытожить — инкапсуляци + абстракция, (еще раз настою на том, что порознь их нельзя рассматривать, это две тесно связанные концепции которые имеют практический смысл только в синергии) это механизм борьбы со сложностью, не только в программировании, вообще везде, в любой человеческой деятельности. В этом их смысл. Если ваши абстракции плохие -> ваш код сложный -> ваш код плохой (говнокодом его еще называют в сообществе программистов).
Почитать на эту тему можно следующее: Р.Мартин — Чистая архитектура (начать с глав про SOLID прицнипы), С.Макконел — Совершенный код (главу про классы обязательно, остальное желательно (очень желательно)), там в общем-то вам расскажут то что я вам сейчас рассказал, только более подробно, по больше примеров и дадут обоснование сложности, назвав борьбу с ней — Главным техническим императивом. Шлифануть это книгой банды четырех. Сами паттерны не обязательно начинать учить (да и рано вам еще), но вот введение и часть про программирование на основе интерфейса, а не реализации — самое оно, это дополнит картину.

UPD: тот факт, что мы в классе стек собрали его функционал (функции pop,push,…) обьединенные одной общей темой и есть факт инкапсуляции.



@sergey-gornostaev

Попробуйте учебники читать, а не видео смотреть. Все принципы ООП, сам ООП и другие парадигмы, а также шаблоны проектирования существуют для управления сложностью. Понять всё это проще всего тогда, когда столкнулся с десятилетнем легаси в проекте с большой командной.



@Griboks

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

Зачем нужна инкапсуляция? Чтобы абстрагироваться от деталей реализации. Например, если у вас есть сетевой пакет данных (который передаётся по IP), то вам нет смысла разбирать, что там передаётся внутри (например, заголовки http запроса), а вы просто инкапсулируете это всё дело как payload (полезные данные пакета) и дальше уже работаете с конкретно IP составляющей пакета (src, dst, payload ,checksum,…).

Другой пример: автомобиль. Когда вы хотите поехать, вы нажимаете несколько кнопок, рычагов, ключ поворачиваете. Согласитесь, что вам не интересно знать напряжение на двигателе во время поездки. Ещё более неудобным было бы видеть огромную приборную панель как в самолёте, когда вы хотите просто нажать на газ и поворачивать руль.

Иными словами, когда вы работаете с классом, некоторые его члены вы не хотите видеть, чтобы не допустить ошибку во внешнем когде. Также иногда полезно абстрагироваться (generic, шаблоны, наследование, полиморфизм, макросы, метаклассы) для экономии сил и времени (переиспользование кода).

p.s.
Думаю, вам надо уточнить значение термина инкапсуляция.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *