Что такое инкапсуляция в программировании
Перейти к содержимому

Что такое инкапсуляция в программировании

  • автор:

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

При первом знакомстве со стуртурами мы получили возможность объединять данные, оставляя их доступными к изменению извне. Также функция length было объявленная как функция в объекту Segment. Что если поместить реализацию этой функции в структуру, тем самым сделав ее неотъемлемой частью структуры и “скрыв” из глобального списка функций (другими словами зачем нам эта отдельная глобальная функция, если она применима только Segment)? Реализовать это можно следующим образом (поместив реализация функции в тело struct)

В примере мы поместили реализацию функции. Можно описать короткое объявление структуры, поместив реализацию функции length вне её:

Из примера видно, что чтобы поместить реализцаию функции структуры нужно соблюсти соответствующий формат, а именно: возвращаемый_тип имя_структуры::имя_функции(параметры)

Оба примера равнозначны и употребимы. Какой из них выбрать зависит от желания разработчика или от правил форматирования кода. Например, если реализация функции состоит из 1-2 строк, то ее можно реализоавать в месте объявленяи. Если реализация много-строчна, то вынести, а в структуре оставить только объявление.

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

В данном примере мы рассмотрели первый пример инкапсуляции (или скорытия реализцаии). В общем инкапсуляция является фундаментом объектного подхода к разработке ПО, в процессе которого данные объекта и детали реализации скрываются в самом объекте.

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

Без нее теряют смысл остальные основополагающие принципы объектно-ориентированного программирования (ООП): наследование и полиморфизм (будут рассмотрены позже).

Сущность инкапсуляции можно отразить формулой: открытый интерфейс + скрытая реализация

ООП с примерами (часть 2)

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

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

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

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

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

Теперь вернёмся в сегодняшний день к современным чудесам автопрома с коробкой-автоматом. На самом деле, по сути, ничего не изменилось. Бензонасос всё так же поставляет бензин в двигатель, дифференциалы обеспечивают поворот колёс на различающиеся углы, коленвал превращает поступательное движение поршня во вращательное движение колёс. Прогресс в другом. Сейчас все эти действия скрыты от пользователя и позволяют ему крутить руль и нажимать на педаль газа, не задумываясь, что в это время происходит с инжектором, дроссельной заслонкой и распредвалом. Именно сокрытие внутренних процессов, происходящих в автомобиле, позволяет эффективно его использовать даже тем, кто не является профессионалом-автомехаником с двадцатилетним стажем. Это сокрытие в ООП носит название инкапсуляции.

Инкапсуляция – это свойство системы, позволяющее объединить данные и методы, работающие с ними, в классе и скрыть детали
реализации от пользователя.

Инкапсуляция неразрывно связана с понятием интерфейса класса. По сути, всё то, что не входит в интерфейс, инкапсулируется в классе.

Абстракция

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

Абстрагирование – это способ выделить набор значимых характеристик объекта, исключая из рассмотрения незначимые. Соответственно, абстракция – это набор всех таких характеристик.

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

Полиморфизм

Любое обучение вождению не имело бы смысла, если бы человек, научившийся водить, скажем, ВАЗ 2106 не мог потом водить ВАЗ 2110 или BMW X3. С другой стороны, трудно представить человека, который смог бы нормально управлять автомобилем, в котором педаль газа находится левее педали тормоза, а вместо руля – джойстик.

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

Полиморфизм – это свойство системы использовать объекты с одинаковым интерфейсом без информации о типе и внутренней структуре объекта.

Например, если вы читаете данные из файла, то, очевидно, в классе, реализующем файловый поток, будет присутствовать метод похожий на следующий: byte[] readBytes( int n );
Предположим теперь, что вам необходимо считывать те же данные из сокета. В классе, реализующем сокет, также будет присутствовать метод readBytes. Достаточно заменить в вашей системе объект одного класса на объект другого класса, и результат будет достигнут.

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

Наследование

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

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

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

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

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

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

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

Инкапсуляция в программировании — это принцип, согласно которому внутреннее устройство сущностей нужно объединять в специальной «оболочке» и скрывать от вмешательств извне. Доступ к объектам возможен через специальные открытые методы, а напрямую обратиться к их содержимому нельзя.

https://amdy.su/wp-admin/options-general.php?page=ad-inserter.php#tab-8

«IT-специалист с нуля» наш лучший курс для старта в IT

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

Обычно содержимое заключается в специальную программную оболочку, которая закрывает данные от внешних обращений. Принцип похож на автоматическую коробку передач: вам не приходится вручную управлять каждым элементом системы, более того — во время управления машиной к ним нет доступа. Есть только коробочка с рычагом, в качестве которой в программировании выступают открытые методы. Это понятно из названия: сущность оказывается «в капсуле», изолированной от внешнего мира.

Попробуйте 9 профессий за 2 месяца и выберите подходящую вам

vsrat_7 1 (1)

Для чего нужна инкапсуляция

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

Объяснить ее значимость поможет подход «от обратного». Вот как выглядела бы работа с кодом без инкапсуляции:

  • Логика и поведение не разделяются — это значит, что если объект должен взаимодействовать с другим, ему придется учитывать его структуру;
  • В любой объект можно обратиться извне напрямую — просто изменить внутреннюю переменную или сделать что-то еще;
  • В результате код усложняется, а внутри объектов возникает путаница, которая может привести к ошибкам.

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

Инкапсуляция, абстракция и сокрытие данных

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

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

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

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

Соответственно, различаются и реализации обоих принципов. Хотя тут многое зависит от языка программирования: в некоторых языках, например, C++, инкапсуляция без сокрытия считается бессмысленной. А в других, таких как Python, есть инкапсуляция, но нет сокрытия. Есть и языки, которые жестко разделяют два понятия — так, что они описываются по-разному.

Курс для новичков «IT-специалист
с нуля» – разберемся, какая профессия вам подходит, и поможем вам ее освоить

Как выглядит реализация инкапсуляции

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

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

Функции внутри объекта называются методами, а данные — свойствами. Они разные, но объединены внутри одной сущности, как и предписывает принцип инкапсуляции.

Как разработчики инкапсулируют данные

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

  • Свойства — это переменные, «лежащие» внутри объектов. Они могут быть любого типа, а иногда и сами являются объектами. В переменных хранятся данные. Если какая-то переменная является свойством, ее содержимое по умолчанию скрыто. Как открывать и запрещать доступ к свойствам, мы расскажем ниже.
  • Методы — это функции внутри объектов. Они не просто хранят данные, а совершают какое-то действие. Важное отличие метода от обычной функции — его можно вызвать только для объекта, в котором он находится. Вызов метода отличается и внешне: в большинстве языков сначала пишется имя объекта, а потом, через точку — название метода и аргументы. А еще для вызова метода ничего не нужно импортировать — все уже есть в объекте, и это еще один пример целостности инкапсулированной сущности.

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

  • Геттер — это метод объекта, который возвращает значение свойства этого объекта. Например, у объекта в свойстве value написано 15. Тогда геттер getValue() будет возвращать 15.
  • Сеттер — это метод, который изменяет значение свойства, задает его (set). Например, гипотетический метод setValue(x) будет менять значение свойства value. Аргумент x — это новое значение свойства, при вызове сеттера туда подставляются данные.

Геттеры и сеттеры важны для инкапсуляции, потому что позволяют не вмешиваться во внутреннюю структуру объекта. Они работают с ним сами, а значит, нет нужды «лезть» в объект извне — данные передадут геттеры и сеттеры. Так снижается риск ошибки при работе с данными в объекте.

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

Модификаторы тоже могут иметь разный синтаксис в зависимости от языка. Классическое обозначение, принятое в языках C и C++:

  • public — объект, функция или метод доступны для всех. Другие сущности могут читать оттуда данные и изменять их. Свойство публичного объекта можно получить, просто написав его название через точку: <имя объекта>.<имя свойства>. С такими данными легко работать, для них не нужны геттеры и сеттеры, но информация оказывается уязвима.
  • private — содержимое объекта доступно только для других его составных частей. Например, метод объекта может вызывать данные из этого же объекта напрямую — а какой-нибудь код снаружи уже не сможет.
  • protected — содержимое объекта доступно ему самому и его производным, например, потомкам.

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

В некоторых языках, например, C#, есть еще вариант internal — доступ открыт только из одного файла. В других файлах нельзя будет создать такой объект. Такой модификатор задается классу.

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

Слово abstract описывает неполные, «схематичные» сущности, которые используются, чтобы наследовать от них более подробные. Объект абстрактного класса нельзя создать. Зато можно отнаследовать от него несколько других классов и создать уже их объекты — для того абстрактные сущности и нужны.

А слово sealed, наоборот, «запечатывает» класс и запрещает создавать его потомков. Это нужно для защиты от ситуаций, когда наследование может сломать работу кода.

Как начать работать с инкапсуляцией

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

Если вы интересуетесь IT — приглашаем на курсы! Выберите и получите новую профессию, востребованную на рынке.

Наш лучший курс для старта в IT. За 2 месяца вы пробуете себя в девяти разных профессиях: мобильной и веб-разработке, тестировании, аналитике и даже Data Science — выберите подходящую и сразу освойте ее.

картинка (75)

Наш лучший курс для старта в IT. За 2 месяца вы пробуете себя в девяти разных профессиях: мобильной и веб-разработке, тестировании, аналитике и даже Data Science — выберите подходящую и сразу освойте ее.

☕ Учебник по Java: инкапсуляция на простых примерах

☕ Учебник по Java: инкапсуляция на простых примерах

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

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

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

Не теряя времени, разберем пример, наглядно демонстрирующий рассматриваемую концепцию и то, как она работает в Java.

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

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

Рассмотрим ее реализацию на примере, описывающем работу кофемашины.

Создадим класс Machinе с атрибутами config , beans , grinder и brewingUnit , хранящими текущее состояние объекта. Методы brewCoffee , brewEspresso , brewFilterCoffee и addBeans реализуют набор операций над этими атрибутами.

Пример 1

Скрытие информации в Java

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

Модификаторы доступа

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

  1. private.
  2. no modifier.
  3. protected.
  4. public.

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

Модификатор private

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

В нашем примере мы используем его, чтобы ограничить доступ ко всем атрибутам и методам brewEspresso и brewFilter . Эти атрибуты и методы должны использоваться только в классе Machine и не являются частью общедоступного API. Вначале это может показаться немного запутанным. Однако очень полезно, когда классы в вашем пакете реализуют четко определенный набор логики. Это также удобно, если вы хотите управлять API, доступным для классов за пределами этого пакета. Впоследствии вы можете использовать видимость пакета для реализации метода, используемого только классами в этом пакете.

Модификатор no modifier

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

Модификатор protected

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

Модификатор public

Доступ к методам и атрибутам, использующим модификатор public , можно получить как в текущем классе, так и во всех других классах.

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

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

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

Пример 2

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

Класс Coffee использует два закрытых атрибута для хранения информации: CoffeeSelection и quantity . Модификатор доступа private делает оба атрибута недоступными для других классов в том же или других пакетах. Если вы хотите получить информацию о текущем состоянии объекта, вы можете вызвать один из общедоступных методов.

Метод getSelection обеспечивает доступ для чтения к атрибуту selection . Он представляет тип кофе, приготовленный кофемашиной. Как видно из фрагмента кода, мы не реализовали метод set для этого атрибута, поскольку мы не можем изменить сорт кофе после того, как он заварен. Доступное количество напитка меняется со временем. После каждого глотка в вашей чашке остается немного меньше. Поэтому мы реализовали метод получения и установки для атрибута quantity .

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

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

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

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