Инкапсуляция (программирование)

Инкапсуляция

В объектно-ориентированном программировании инкапсуляция (также называемая сокрытием информации) – это процесс скрытия деталей о том, как реализован объект, от пользователей этого объекта. Вместо этого пользователи получают доступ к объекту через открытый, общедоступный интерфейс. Таким образом, пользователи могут использовать объект, не понимая, как он реализован.

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

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

Преимущество: инкапсулированные классы проще в использовании и уменьшают сложность ваших программ

При полностью инкапсулированном классе для его использования вам нужно только знать, какие функции-члены открыты, какие аргументы они принимают и какие значения возвращают. Неважно, как этот класс был реализован внутри. Например, класс, содержащий список имен, мог быть реализован с использованием динамического массива строк в стиле C, std::array, std::vector, std::map, std::list или одной из многих других структур данных. Чтобы использовать этот класс, вам не нужно знать (или беспокоиться), какую именно структуру данных он использует. Это значительно снижает сложность ваших программ, а также уменьшает количество ошибок. Это ключевое преимущество инкапсуляции.

Все классы стандартной библиотеки C++ инкапсулированы. Представьте себе, насколько сложнее был бы C++, если бы вам нужно было понять, как были реализованы std::string, std::vector или std::cout, чтобы их можно было использовать!

Преимущество: инкапсулированные классы помогают защитить ваши данные и предотвратить неправильное использование

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

Например, предположим, что мы пишем строковый класс. Мы могли бы начать так:

Эти две переменные имеют внутреннюю связь: m_length всегда должна быть равна длине строки, содержащейся в m_string (это соединение называется инвариантом). Если бы m_length была открытой, любой мог бы изменить длину строки, не изменяя m_string (или наоборот). Это поставило бы класс в несогласованное состояние, что могло бы вызвать всевозможные странные проблемы. Делая m_length и m_string закрытыми, пользователи вынуждены для работы с этим классом использовать любые доступные открытые функции-члены (а эти функции-члены могут гарантировать, что m_length и m_string всегда устанавливаются правильно).

Мы также можем помочь защитить пользователя от ошибок при использовании нашего класса. Рассмотрим класс с открытой переменной-членом массива:

Если пользователи могут получить доступ к массиву напрямую, они могут попытаться использовать его с недопустимым индексом, что приведет к неопределенным результатам:

Однако если мы сделаем массив закрытым, то сможем заставить пользователя использовать функцию, которая сначала проверяет, что индекс корректен:

Таким образом, мы защитили целостность нашей программы. Кстати, функции at() классов std::array и std::vector делают нечто очень похожее!

Преимущество: инкапсулированные классы легче изменять

Рассмотрим простой пример:

Хотя эта программа работает нормально, что произойдет, если мы решим переименовать переменную m_value1 или изменить ее тип? Мы сломаем не только эту программу, но, вероятно, и большинство программ, которые также используют класс Something!

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

Вот инкапсулированная версия этого класса, который использует функции для доступа к m_value1:

Теперь давайте изменим реализацию класса:

Обратите внимание: поскольку мы не изменяли прототипы каких-либо функций в открытом интерфейсе нашего класса, наша программа, использующая данный класс, продолжает работать без каких-либо изменений.

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

Преимущество: инкапсулированные классы легче отлаживать

И, наконец, инкапсуляция помогает вам отлаживать программу, когда что-то идет не так. Часто, когда программа работает некорректно, это происходит потому, что одна из наших переменных-членов имеет неправильное значение. Если получить доступ к переменной напрямую могут все, то отследить, какой фрагмент кода изменил эту переменную, может быть трудно (это может быть любой, и вам нужно будет установить точки останова везде, чтобы выяснить, где же ее изменили). Однако если для изменения значения все должны вызывать одну и ту же открытую функцию, вы можете просто установить точку останова на этой функции и наблюдать, как каждый вызывающий меняет значение, пока не увидите, где что-то пошло не так.

Видео

Инкапсуляция [ ]

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

Пользователь может взаимодействовать с объектом только через этот интерфейс. Реализуется с помощью ключевого слова: public.

Пользователь не может использовать закрытые данные и методы. Реализуется с помощью ключевых слов: private, protected, internal.))

Инкапсуляция — один из четырёх важнейших механизмов объектно-ориентированного программирования (наряду с абстракцией, полиморфизмом и наследованием).

Сокрытие реализации целесообразно применять в следующих случаях:

предельная локализация изменений при необходимости таких изменений,

прогнозируемость изменений (какие изменения в коде надо сделать для заданного изменения функциональности) и прогнозируемость последствий изменений.

Преимущества и недостатки использования инкапсуляции?

Преимущества:

  1. Полный контроль над входящими и исходящими данными.
  2. Можно без боязни сломать все остальное приложение, править реализацию методов компонентов. Так как во всем остальном приложении фигурирует только интерфейс, а Вы меняете только реализацию логики.

Недостатки:

  1. Если Вы нашли ошибку в библиотеке которую используете, то Вам будет трудно ее исправить.
  2. Снижается скорость работы приложения.

Но последний пункт, думаю, вообще брать нет смысла, с учетом мощностей которые теперь доступны. И плюсов которые она предоставляет.

Как посмотреть данные скрытого поля или даже изменить? #

В нашем классе с котом есть конструктор, который создаёт котика без паспорта прививок. Если мы сделаем ему паспорт, то мы можем создать метод, который меняет значение поля. Метод изменяющий поле называют “сетер”.

Мы передаём новое значение и изменяем его. В название поля всегда есть слово set и потому их так и прозвали.

Метод, который показывает нам значение поля, называется гетер. Потому что в название метода всегда есть get.

Ну почти всегда. Всегда если это не boolean. Запомните это, пожалуйста. Гетеры для остальных полей класса Cat:

Как мы видим конвенция для названия метода достаточно проста. Используй get, is или set и само название поли и соедини их через CamelCase нотацию.

Сам класс теперь выглядит вот так.

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

Очень часто (и такое будет в домашнем задании) лепят гетеры ко всем полям класса. Разумно делать только те гетеры и тем более сетеры, которые действительно нужны.

Теги

Adblock
detector