Инкапсуляция в программировании — это принцип, согласно которому внутреннее устройство сущностей нужно объединять в специальной «оболочке» и скрывать от вмешательств извне. Доступ к объектам возможен через специальные открытые методы, а напрямую обратиться к их содержимому нельзя.
Инкапсуляцию также описывают как принцип разделения логики и поведения. Логика — то, как что-то устроено внутри. Поведение — то, как оно взаимодействует с другими сущностями. Разделение этих двух понятий упрощает взаимодействие объектов в коде.
Обычно содержимое заключается в специальную программную оболочку, которая закрывает данные от внешних обращений. Принцип похож на автоматическую коробку передач: вам не приходится вручную управлять каждым элементом системы, более того — во время управления машиной к ним нет доступа. Есть только коробочка с рычагом, в качестве которой в программировании выступают открытые методы. Это понятно из названия: сущность оказывается «в капсуле», изолированной от внешнего мира.
Для чего нужна инкапсуляция
Инкапсуляция считается одним из четырех основных принципов ООП — объектно-ориентированного программирования. Этот подход представляет сущности в коде как классы и объекты, позволяет «строить» код из них, как из кирпичиков. Но чтобы объекты грамотно выполняли свои задачи и не ломались, нужна инкапсуляция.
Объяснить ее значимость поможет подход «от обратного». Вот как выглядела бы работа с кодом без инкапсуляции:
- Логика и поведение не разделяются — это значит, что если объект должен взаимодействовать с другим, ему придется учитывать его структуру;
- В любой объект можно обратиться извне напрямую — просто изменить внутреннюю переменную или сделать что-то еще;
- В результате код усложняется, а внутри объектов возникает путаница, которая может привести к ошибкам.
Поэтому инкапсуляция нужна — так код становится более упорядоченным и повышается отказоустойчивость. Ведь если сломается инкапсулированный объект, это не повлияет на работу других. Примерно как сломанная кнопка не приводит к поломке всего устройства.
Инкапсуляция, абстракция и сокрытие данных
При чем тут абстракция. Инкапсуляция тесно связана с понятием абстракции данных — одним из самых старых принципов ООП. Это понятие говорит, что любая сущность должна описываться каким-то минимумом ее возможностей. Мелкие особенности уже не важны для создания полного описания. Например, чтобы пользоваться телефоном, нам неважно, какого он цвета — с точки зрения функциональности это неважный параметр.
Абстракция помогает работать с объектами и не обращать внимания на то, как они устроены внутри. А для этого как раз нужна инкапсуляция.
Отличие от сокрытия данных. Но из определения абстракции необязательно следует сокрытие данных. Поэтому сейчас считается, что сокрытие данных от воздействий извне и инкапсуляция — немного разные вещи. Они различаются целью:
- Сокрытие нужно, чтобы обеспечить безопасность данных, и подразумевает невозможность доступа;
- Инкапсуляция нужна, чтобы обеспечить целостность объекта и дать возможность пользоваться им, не вдаваясь в подробности его реализации. При этом технический доступ к объекту в некоторых случаях может сохраниться.
Соответственно, различаются и реализации обоих принципов. Хотя тут многое зависит от языка программирования: в некоторых языках, например, C++, инкапсуляция без сокрытия считается бессмысленной. А в других, таких как Python, есть инкапсуляция, но нет сокрытия. Есть и языки, которые жестко разделяют два понятия — так, что они описываются по-разному.
Как выглядит реализация инкапсуляции
Идея инкапсуляции реализована в ООП с помощью классов и объектов. Класс — это абстрактное описание, по которому создаются объекты, работающие в коде. Его можно сравнить с чертежом, который описывает, как будет работать та или иная сущность. В то же время объекты — реальные переменные, которые хранят в себе данные, выполняют функции и работают. Можно сказать, это экземпляры техники, созданные по чертежам-классам.
Такое разделение помогает инкапсуляции — создает отдельную сущность, в которую входит определенный набор функций и данных. Класс описывает эту сущность с помощью идеи абстракции, о которой мы говорили выше. Получается целостный законченный объект, который работает без вмешательства других.
Функции внутри объекта называются методами, а данные — свойствами. Они разные, но объединены внутри одной сущности, как и предписывает принцип инкапсуляции.
Как разработчики инкапсулируют данные
Методы и свойства. Мы уже говорили о том, что классы и объекты — важный инструмент инкапсуляции. Стоит рассказать подробнее о методах и свойствах объектов. За счет них во многом обеспечивается инкапсуляция.
- Свойства — это переменные, «лежащие» внутри объектов. Они могут быть любого типа, а иногда и сами являются объектами. В переменных хранятся данные. Если какая-то переменная является свойством, ее содержимое по умолчанию скрыто. Как открывать и запрещать доступ к свойствам, мы расскажем ниже.
- Методы — это функции внутри объектов. Они не просто хранят данные, а совершают какое-то действие. Важное отличие метода от обычной функции — его можно вызвать только для объекта, в котором он находится. Вызов метода отличается и внешне: в большинстве языков сначала пишется имя объекта, а потом, через точку — название метода и аргументы. А еще для вызова метода ничего не нужно импортировать — все уже есть в объекте, и это еще один пример целостности инкапсулированной сущности.
Геттеры и сеттеры. Выше мы говорили, что свойства по умолчанию скрыты от посторонних. Несмотря на то что во многих случаях обратиться к ним напрямую через объект можно, в ООП это считается не лучшей практикой. Поэтому для работы со свойствами используют специальные методы — геттеры и сеттеры. Названия таких методов обычно начинаются со слов get и set — другие имена не запрещены синтаксисом, но считаются плохим тоном.
- Геттер — это метод объекта, который возвращает значение свойства этого объекта. Например, у объекта в свойстве value написано 15. Тогда геттер getValue() будет возвращать 15.
- Сеттер — это метод, который изменяет значение свойства, задает его (set). Например, гипотетический метод setValue(x) будет менять значение свойства value. Аргумент x — это новое значение свойства, при вызове сеттера туда подставляются данные.
Геттеры и сеттеры важны для инкапсуляции, потому что позволяют не вмешиваться во внутреннюю структуру объекта. Они работают с ним сами, а значит, нет нужды «лезть» в объект извне — данные передадут геттеры и сеттеры. Так снижается риск ошибки при работе с данными в объекте.
Модификаторы доступа. Теоретически обратиться в объект снаружи кода можно, но тут есть свои детали. Поведение по умолчанию может различаться для разных языков, но обычно возможность доступа к объекту можно настроить. Программист в коде сам описывает правила доступа. Для этого используются специальные ключевые слова — модификаторы доступа.
Модификаторы тоже могут иметь разный синтаксис в зависимости от языка. Классическое обозначение, принятое в языках C и C++:
- public — объект, функция или метод доступны для всех. Другие сущности могут читать оттуда данные и изменять их. Свойство публичного объекта можно получить, просто написав его название через точку: <имя объекта>.<имя свойства>. С такими данными легко работать, для них не нужны геттеры и сеттеры, но информация оказывается уязвима.
- private — содержимое объекта доступно только для других его составных частей. Например, метод объекта может вызывать данные из этого же объекта напрямую — а какой-нибудь код снаружи уже не сможет.
- protected — содержимое объекта доступно ему самому и его производным, например, потомкам.
Модификаторы задаются в классе, который описывает объект. Их можно задать самому классу или его содержимому — разным методам и свойствам.
В некоторых языках, например, C#, есть еще вариант internal — доступ открыт только из одного файла. В других файлах нельзя будет создать такой объект. Такой модификатор задается классу.
Ключевые слова. Ряд языков поддерживает и другие возможности, способствующие инкапсуляции. Обычно они реализуются с помощью ключевых слов. Например, static дает возможность сделать метод класса статичным — и запускать, даже если объект этого класса не создан.
Слово abstract описывает неполные, «схематичные» сущности, которые используются, чтобы наследовать от них более подробные. Объект абстрактного класса нельзя создать. Зато можно отнаследовать от него несколько других классов и создать уже их объекты — для того абстрактные сущности и нужны.
А слово sealed, наоборот, «запечатывает» класс и запрещает создавать его потомков. Это нужно для защиты от ситуаций, когда наследование может сломать работу кода.
Как начать работать с инкапсуляцией
Инкапсуляция — это часть ООП, а ООП начинают глубоко изучать уже после знакомства с базовыми возможностями языка. Но некоторыми вещами, которые реализованы по принципу инкапсуляции, человек начинает пользоваться еще на ранних стадиях обучения. Например, стандартные методы встроенных объектов — сортировка массива, получение его длины и другие. Просто позже, на более глубоком уровне изучения, начинающий разработчик поймет, с чем все время имел дело.
Если вы интересуетесь IT — приглашаем на курсы! Выберите и получите новую профессию, востребованную на рынке.
0 комментариев