Что значит инкапсулированный файл

Обновлено: 07.07.2024

  • языковой механизм ограничения доступа к определённым компонентам объекта;
  • языковая конструкция, способствующая объединению данных с методами (или другими функциями), обрабатывающими эти данные.

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

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

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

Содержание

Примеры

Класс А инкапсулирует свойства Aa, Ab и метод DoSomething, представляя внешний интерфейс ReturnSomething, a, b.

При этом мы можем отдельно изменять как само значение Value, так и его строковое представление, и в некоторый момент может возникнуть их несоответствие (например, в результате исключения). Пример реализации с использованием инкапсуляции:

Здесь доступ к переменным valueDouble и valueString возможен только через свойства Value и ValueString. Если мы попытаемся присвоить свойству ValueString некорректную строку и возникнет исключение в момент конвертации, то внутренние переменные останутся в прежнем, согласованном состоянии, поскольку исключение вызывает выход из процедуры.

Delphi

В Delphi для создания скрытых полей или методов их достаточно объявить в секции private .

Для создания интерфейса доступа к скрытым полям в Delphi введены свойства.

В этом примере закрыты свойства $a и $b для класса A с целью предотвращения повреждения этих свойств другим кодом, которому необходимо предоставить только права на чтение.

JavaScript

См. также

Wikimedia Foundation . 2010 .

Полезное

Смотреть что такое "Инкапсуляция (программирование)" в других словарях:

Полиморфизм (программирование) — У этого термина существуют и другие значения, см. Полиморфизм. Эта статья или раздел нуждается в переработке. Пожалуйста, улучшите статью … Википедия

Уровень абстракции (программирование) — У этого термина существуют и другие значения, см. Абстракция (значения). Типичное представление архитектуры компьютера в … Википедия

Объектно-ориентированное программирование на Питоне — С самого начала Питон проектировался как объектно ориентированный язык программирования [1]. Содержание 1 Введение 1.1 Принципы ООП … Википедия

Что значит инкапсулировать ? Слово инкапсуляция я понимаю как сокрытие данных о реализации некоторых участков кода для повышения уровня абстракции. Но что означает инкапсулировать до конца не ясно. В голову приходит мысль о том, что это процесс сокрытия данных о реализации. Но мое представление не всегда совпадает с контекстом из книги.

7,308 14 14 золотых знаков 56 56 серебряных знаков 108 108 бронзовых знаков

В разработке ПО есть два схожих понятия – инкапсуляция и сокрытия информации. Кто-то считает, что это синонимы, кто-то нет, но это не так и важно.

Немного истории: Дэвид Парнас в году эдак 70-м в статье “On the Criteria To Be Used in Decomposing Systems into Modules” впервые ввел понятие сокрытия информации, как ключевого инструмента проектирования. Звучал этот принцип примерно так: декомпозиция системы на модули не должна основываться на анализе блок схем или потоков исполнения. Вместо этого, каждый модуль должен прятать внутри некоторое решение (design decision), предоставляя минимальное количество информации о нем своим клиентам.

Вот небольшой пример.

Допустим, вы разрабатываете ынтырпрайз приложение, которое делает что-то важное. Любое нормальное приложение обычно требует некоторой конфигурации: ну, параметры подключения к БД или серверу, и другую ценную информацию. И вот, матерый артихектор (*) вместе с не менее матерым клиентом просят прочитать конфигурацию из конфигурационного файла.

(*) это не опечатка, пожалуйста, не правьте это!

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

Теперь вы становитесь перед выбором: вы можете «размазать» сведения о конфигурации ровным слоем по всему приложению. Каждый компонент, которому нужны некоторые параметры, сам полезет в app config, вытянет оттуда нужные данные, пропарсит xml или json и будет готов служить. С другой стороны, очевидно, что решение о том, где именно хранится конфигурация и в каком формате, может измениться в будущем. Поэтому более вменяемым решением будет скрыть информацию о местоположении и формате конфигурации в одном модуле, например, с помощью классов Configuration и ConfigurationProvider . В этом случае, когда (да, именно, «когда», а не «если») требования изменятся, то поменяется лишь реализация класса ConfigurationProvider , а все остальные пользователи этого класса или конфигурации останутся неизменными. Аналогично, при изменении формата, поменяется тоже только процесс парсинга, а не потребители конфигурации.

Этот пример кажется надуманным, но это не так! Мы довольно часто сталкиваемся с изменчивостью требований, но используем, к сожалению, один из двух подходов:

• Полностью игнорируем возможность изменения требований и делаем все в лоб или

• Создаем супер сложное решение с десятком уровней косвенности, которое должно выдержать изменения требований в любом направлении без изменения кода вообще.

Более же разумный подход находится где-то по середине. Каждый раз, когда я начинаю разработку некоторой фичи, я думаю, сколько кусков в коде придется поменять, если требования или детали реализации существенно изменятся. При этом я не стараюсь свести количество изменений к 1 (ну, типа, если мы следуем SRP, то должно быть только одно место, в случае изменения требованй). Я стараюсь, чтобы этих мест было мало, а изменения были простыми.

Собственно, это и есть суть information hiding и его младшей сестры – инкапсуляции.


Инкапсуляция это набор инструментов для управления доступом к данным или методам которые управляют этими данными. С детальным определением термина “инкапсуляция” можно ознакомиться в моей предыдущей публикации на Хабре по этой ссылке. Эта статья сфокусирована на примерах инкапсуляции в Си++ и Си.

По умолчанию, в классе ( class ) данные и методы приватные ( private ); они могут быть прочитаны и изменены только классом к которому принадлежат. Уровень доступа может быть изменен при помощи соответствующих ключевых слов которые предоставляет Си++.

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

  • публичные ( public ) данные — доступны всем;
  • защищенные ( protected ) — доступны только классу и дочерним классам;
  • приватные ( private ) —доступны только классу которому они принадлежат.

Для краткости, только два уровня (приватный и публичный) будут освещены в примерах.

Пример инкапсуляции

В классе Contact , публичные переменные и методы доступны из основной программы ( main ). Приватные переменные и методы могут прочитаны, вызваны или изменены только самим классом.

Попытка напечатать или изменить приватную переменную mobile_number из основной программы ( main ) вызовет ошибку при компиляции потому как доступ к приватным данным в классе ограничен.

Нарушение инкапсуляции с Друзьями (Хорошая практика)

В Си++ присутствует ключевое слово “друг” ( friend ) которое позволяет добавить исключения в общие правила доступа к данным. Если функция или класс названы другом ( friend ) класса Contact — они получают свободный доступ к защищенным или приватным данным.

Существует два основных правила дружбы — дружба не наследуется и не взаимна. Также, наличие “друзей” не изменяет уровень защищенности данных — приватные данные остаются приватными с исключением в виде “друга”.

В этом примере, функция print_numbers() — обычная функция, не метод класса Contact . Объявление функции print_numbers() “другом” класса Contact — единственная причина по которой функция print_numbers() имеет доступ к приватным данным. Если убрать строку с определением друга — код не скомпилируется.

Примечание: друзьями лучше не злоупотреблять. Добавление друга стоит рассматривать как исключение, не как общую практику.

Нарушение инкапсуляции с Преобразованием типов и Указателями (Плохая практика)

Прежде всего, стоит заметить что использовать указатели и преобразование типов таким способом — плохая идея. Этот способ не гарантирует получения нужных данных. Он плохо читается и плохо поддерживается. Невзирая на это, он существует.

Си++ получил в наследство от Си множество инструментов, один из которых — преобразование типов ( typecasting ). По умолчанию, все переменные и методы в классе приватные. В то же время, стандартный уровень доступа к данным в структуре ( struct ) — публичный. Возможно создать структуру или полностью публичный класс в котором данные будут расположены идентично данным в классе Contact и используя преобразование типов получить доступ к приватным данным.

Приватные данные были прочитаны и изменены благодаря преобразованию типов

Традиционно считается что инкапсуляция — один из ключевых ООП принципов. Тем не менее, это не лимитирует использование этого принципа в процедурно-ориентированных языках. В Си, инкапсуляция используется давно, невзирая на отсутствие ключевых слов “приватный” и “публичный”.

Приватные переменные

В контексте инкапсуляции, все данные в Си могут быть рассмотрены как публичные по умолчанию. Уровень доступа к переменным в структурах ( struct ) может быть изменен на приватный если изолировать их определение от основной программы. Нужный эффект может быть достигнут при использовании отдельных заголовочных (header, .h) и исходных (source, .c) файлов.

В данном примере, структура была определена в отдельном исходном файле “private_var.c”. Поскольку инициализация структуры в Си требует выделения и освобождения памяти, несколько вспомогательных функций были добавлены.

В соответствующем заголовочном файле "private_var.h", структура Contact была объявлена, но ее содержание осталось скрытым для основной программы.

Таким образом, для “main.c” содержание структуры неизвестно и попытки прочитать или изменить приватные данные вызовут ошибку при компиляции.

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

Преобразование типов может быть использовано для преодоления инкапсуляции в Си также как и в Си++, но данный подход уже был описан. Зная, что в структуре данные расположены в порядке их декларации, указатели и арифметика указателей подойдет для достижения цели.

Доступ к переменным в структуре ограничен. Тем не менее, спрятаны только переменные, не память в которой хранятся данные. Указатели можно рассматривать как ссылку на адрес памяти, и если эта память доступна программе — данные сохраненные в этой памяти можно прочитать и изменить. Если указатель назначен на память в которой структура хранит свои данные — их можно прочитать. Используя то же определение структуры (те же “.c” и “.h” файлы) и модифицированный “main.c” файл, ограничение доступа было преодолено.

Данные в структуре были прочитаны и модифицированы

Приватные функции

Функции, будучи внешними ( extern ) по умолчанию, видимы во всей так называемой единице трансляции ( translation unit ). Другими словами, если несколько файлов скомпилированы вместе в один объектный файл, любой из этих файлов сможет получить доступ к любой функции из любого другого файла. Использование ключевого слова “статический” ( static ) при создании функции ограничит ее видимость до файла в котором она была определена.Следовательно, для обеспечения приватности функции необходимо выполнить несколько шагов:

  • функция должна быть объявлена статической ( static ) либо в исходном файле (.c), либо в соответствующем заголовочном файле (.h);
  • определение функции должно находиться в отдельном исходном файле.

В данном примере, в файле “private_funct.c”, была определена статическая функция print_numbers() . К слову, функция delete_contact() успешно вызывает print_numbers() поскольку они находятся в одном файле.

В соответствующем заголовочном файле "private_funct.h", print_numbers() была декларирована как статическая функция.

Основная программа, “main.c”, успешно вызывает print_numbers() опосредовательно через delete_contact() , поскольку обе функции находятся в одном документе. Тем не менее, попытка вызвать print_numbers() из основной программы вызовет ошибку.

Получение доступа к приватным функциям

Вызвать функцию print_numbers() из основной программы возможно. Для этого можно использовать ключевое слово goto или передавать в main указатель на приватную функцию. Оба способа требуют изменений либо в исходном файле “private_funct.c”, либо непосредственно в теле самой функции. Поскольку эти методы не обходят инкапсуляцию а отменяют её, они выходят за рамки этой статьи.

Инкапсуляция существует за пределами ООП языков. Современные ООП языки делают использование инкапсуляции удобным и естественным. Существует множество способов обойти инкапсуляцию и избежание сомнительных практик поможет ее сохранить как в Си, так и в Си++.

Говорят, что тип данных инкапсулирован, если экземпляры этого типа не имеют видимых пользователям компонентов.
Объект состоит из некоторой частной памяти и набора операций . Публичные свойства объекта являются спецификациями операций, составляющими его интерфейс.. . Частные свойства объекта - это набор компонентов, составляющих его частную память.
Если должным образом различать тип и представление, и если добиться скрытости представления, то можно изменять представление без потребности изменять прикладные программы. Нужно всего лишь изменить код, реализующий операции.
Инкапсуляция вступает в некоторый конфликт с потребностью выполнять непредвиденные запросы. Инкапсуляция означает, что доступ к данным может быть произведен только через заранее определенные операции, а смысл непредвиденных запросов, почти по определению, состоит в том, что требуется доступ, способ которого невозможно предопределить. Например, пусть имеется тип данных POINT; предположим, что также имеется (предопределенная) операция для "взятия" (чтения или выборки) X-координаты заданной точки, но нет подобной операции для соответствующей Y-координаты. Тогда невозможно выполнить даже следующие простые запросы и множество подобных:

Получить Y-координату точки P
Выбрать все точки по оси X
Выбрать все точки со значением ординаты меньшим пяти.

Для типа POINT, например, можно было бы определить операции THE_X и THE_Y, что позволило бы производить следующие действия:

Q := THE_Y (P) ;
/* получить Y-координату точки P и присвоить ее Q */
Z := SQRT ( THE_X (P) ** 2 + THE_Y (P) ** 2 ) ;
/* получить расстояние до точки P от точки (0,0) и присвоить его Z */

Таким образом, THE_X и THE_Y действительно раскрывают возможное представление - а именно, декартовы координаты X и Y - и обеспечивают возможность выполнять непредвиденные запросы с точками. Однако это не означает того, что внутри системы точки действительно представлены декартовыми координатами; это значит лишь то, что декартовы координаты являются возможным представлением. В реальном представлении могут использоваться декартовы координаты, полярные координаты R и U или что-нибудь совсем другое. Другими словами, THE_операции не нарушают инкапсуляцию и не подрывают независимость данных. Заметим, кстати, что типы данных DATE и TIME языка SQL представляют пример встроенных типов с раскрытием некоторых возможных представлений. Например, для дат раскрывается возможное представление с компонентами YEAR, MONTH и DAY. Хотя, вероятно, следует добавить, что эти "возможные" представления в SQL, к сожалению, близки к реальным представлениям; в SQL различие между типами и представлениями часто не является четким.

ООП в JavaScript. Инкапсуляция

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

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

  • Программист, работающий с чужим кодом не перегружен лишней информацией
  • Инкапсуляция повышает безопасность кода

Пример без применения инкапсуляции

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

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

// Метод say() покажет какие значения есть у объекта на данный момент.
this.say();

Мы видим, что объект misha уже содержит новые данные вместо первоначальных. Получается, что кто-то может вмешаться в наш код и изменить данные. Чтобы воспрепятствовать такому поведению и придумали инкапсуляцию.

ООП в JavaScript. Инкапсуляция.

Пример создания инкапсуляции

Заменим объекты this.name и this.age на переменные userName и userAge.

// Метод say() покажет какие значения есть у объекта на данный момент.
misha.say();

Мы видим, что данные в переменных никак не изменились. Дело в том, что содержимое переменных созданных внутри функций уже нельзя поменять снаружи.

ООП в JavaScript. Инкапсуляция.

Заключение

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


Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления

Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.

Порекомендуйте эту статью друзьям:

Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):

Она выглядит вот так:

Комментарии ( 0 ):

Читайте также: