17-10-2023
В информатике инкапсуляцией (лат. en capsula) называется упаковка данных и/или функций в единый компонент.
Инкапсуляция, наследование и полиморфизм (в форме ad hoc полиморфизма или полиморфизма подтипов) являются тремя столпами объектно-ориентированного программирования, реализуя в нём принцип абстракции данных (не путать с абстрактными типами данных, реализации которых предоставляют возможность инкапсуляции, но имеют иную природу).
В объектно-ориентированных языках инкапсуляция, как правило, реализуется посредством механизма классов. Некоторые исследователи классифицируют инкапсуляцию как понятие, присущее исключительно объектно-ориентированному программированию, и необходимое для управления сокрытием, но существуют и другие механизмы, рассматривающие эти понятия независимо. Например, применение средств инкапсуляции для многих задач оказывается ненужным в языках, использующих лексическую область видимости, которая обеспечивает полное сокрытие компонентов. Примерами таких языков служат Scheme и Standard ML.
В общем случае, в разных языках программирования термин «инкапсуляция» относится к одной из или обеим одновременно следующим нотациям:
class A { public: int a, b; //данные открытого интерфейса int ReturnSomething(); //метод открытого интерфейса private: int Aa, Ab; //скрытые данные void Do_Something(); //скрытый метод };
Класс А инкапсулирует свойства Aa, Ab и метод Do_Something(), представляя внешний интерфейс ReturnSomething, a, b.
Целью инкапсуляции является обеспечение согласованности внутреннего состояния объекта. В C# для инкапсуляции используются публичные свойства и методы объекта. Переменные, за редким исключением, не должны быть публично доступными. Проиллюстрировать инкапсуляцию можно на простом примере. Допустим, нам необходимо хранить вещественное значение и его строковое представление (например, для того, чтобы не производить каждый раз конвертацию в случае частого использования). Пример реализации без инкапсуляции таков:
class NoEncapsulation { public double ValueDouble; public string ValueString; }
При этом мы можем отдельно изменять как само значение Value, так и его строковое представление, и в некоторый момент может возникнуть их несоответствие (например, в результате исключения). Пример реализации с использованием инкапсуляции:
class EncapsulationExample { private double valueDouble; private string valueString; public double ValueDouble { get { return valueDouble; } set { valueDouble = value; valueString = value.ToString(); } } public string ValueString { get { return valueString; } set { double tmp_value = Convert.ToDouble(value); //здесь может возникнуть исключение valueDouble = tmp_value; valueString = value; } } }
Здесь доступ к переменным valueDouble и valueString возможен только через свойства ValueDouble и ValueString. Если мы попытаемся присвоить свойству ValueString некорректную строку и возникнет исключение в момент конвертации, то внутренние переменные останутся в прежнем, согласованном состоянии, поскольку исключение вызывает выход из процедуры.
В Delphi для создания скрытых полей или методов их достаточно объявить в секции private
.
TMyClass = class private FMyField: Integer; procedure SetMyField(const Value: Integer); function GetMyField: Integer; public property MyField: Integer read GetMyField write SetMyField; end;
Для создания интерфейса доступа к скрытым полям в Delphi введены свойства.
class A { private $a; // скрытое свойство private $b; // скрытое свойство private function DoSomething() //скрытый метод { //actions } public function ReturnSomething() //открытый интерфейс { //actions } };
В этом примере закрыты свойства $a и $b для класса A с целью предотвращения повреждения этих свойств другим кодом, которому необходимо предоставить только права на чтение.
class A { private int a; private int b; private void doSomething() { //скрытый метод //actions } public int getSomething() { //открытый метод return a; } }
var A = function() { // private var _property; var _privateMethod = function() { /* actions */ } // скрытый метод // public this.getProperty = function() { // открытый интерфейс return _property; } this.setProperty = function(value) { // открытый интерфейс _property = value; _privateMethod(); } }
или
var A = function() { // private var _property; var _privateMethod = function() { /* actions */ } // скрытый метод // public return { getProperty: function() { // открытый интерфейс return _property; }, setProperty: function(value) { // открытый интерфейс _property = value; _privateMethod(); } } }
Инкапсуляция (программирование).