Из Википедии, бесплатной энциклопедии
Перейти к навигации Перейти к поиску

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

В классе обычно предоставляются общедоступные методы для более абстрактного доступа или изменения состояния. На практике иногда предоставляются методы (так называемые «геттеры» и «сеттеры» ) для косвенного доступа к значениям, но, хотя это не обязательно является нарушением абстрактной инкапсуляции, они часто считаются признаком потенциально плохого объектно-ориентированного программирования. (ООП) практика проектирования [2] ( Антипаттерн ).

Этот механизм не является уникальным для ООП. Реализации абстрактных типов данных , например модули , предлагают аналогичную форму инкапсуляции. Сходство было объяснено теоретиками языков программирования в терминах экзистенциальных типов . [3]

Значение [ править ]

В объектно-ориентированных языках программирования и других связанных областях инкапсуляция относится к одному из двух связанных, но различных понятий, а иногда и к их комбинации: [4] [5]

  • Языковой механизм для ограничения прямого доступа к некоторым компонентам объекта . [6] [7]
  • Конструкция языка, которая упрощает связывание данных с методами (или другими функциями), работающими с этими данными. [1] [8]

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

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

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

Инкапсуляция и наследование [ править ]

Авторы Design Patterns подробно обсуждают противоречие между наследованием и инкапсуляцией и заявляют, что, по их опыту, дизайнеры злоупотребляют наследованием. Они утверждают, что наследование часто нарушает инкапсуляцию, поскольку наследование предоставляет подклассу сведения о его родительской реализации. [9] Как описано в проблеме йо-йо , чрезмерное использование наследования и, следовательно, инкапсуляции может стать слишком сложным и трудным для отладки.

Скрытие информации [ править ]

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

Некоторые языки, такие как Smalltalk и Ruby, разрешают доступ только через объектные методы, но большинство других (например, C ++ , C # , Delphi или Java ) предлагают программисту определенную степень контроля над тем, что скрыто, обычно с помощью таких ключевых слов, как publicи private. [7] стандарт ISO C ++ относится к protected, privateи publicкак « спецификаторы доступа » , и что они не «скрыть какую - либо информацию». Сокрытие информации достигается путем предоставления скомпилированной версии исходного кода, которая связана через файл заголовка.

Почти всегда есть способ переопределить такую ​​защиту - обычно через API отражения (Ruby, Java, C # и т. Д.), Иногда с помощью такого механизма, как изменение имени ( Python ) или использование специального ключевого слова, как friendв C ++.

Примеры [ править ]

Ограничение полей данных [ править ]

Такие языки, как C ++ , C # , Java , PHP , Swift и Delphi, предлагают способы ограничения доступа к полям данных.

Ниже приведен пример на C #, который показывает, как можно ограничить доступ к полю данных с помощью privateключевого слова:

class  Program {  public  class  Account  {  private  decimal  accountBalance  =  500.00 m ; public  decimal  CheckBalance ()  {  вернуть  это . accountBalance ;  }  } static  void  Main ()  {  Account  myAccount  =  new  Account ();  десятичный  myBalance  =  myAccount . CheckBalance (); / * Этот метод Main может проверять баланс с помощью общедоступного  метода * "CheckBalance", предоставляемого классом "Account"  *, но он не может управлять значением "accountBalance" * /  } }

Ниже приведен пример на Java :

 сотрудник публичного класса  { частная BigDecimal зарплата = новый BigDecimal ( 50000.00 );         public  BigDecimal  getSalary ()  {  вернуть  это . зарплата ;  } public  static  void  main ()  {  Employee  e  =  new  Employee ();  BigDecimal  sal  =  e . getSalary ();  } }

Инкапсуляция также возможна в не объектно-ориентированных языках. В C , например, структура может быть объявлена ​​в общедоступном API через файл заголовка для набора функций, которые работают с элементом данных, содержащим элементы данных, которые недоступны для клиентов API с externключевым словом. [10] [11]

// Заголовочный файл "api.h"struct  Entity ;  // Непрозрачная структура со скрытыми членами// Функции API, которые работают с объектами Entity extern  struct  Entity  *  open_entity ( int  id ); extern  int  process_entity ( структура  Entity  * информация ); extern  void  close_entity ( struct  Entity  * info ); // Ключевые слова extern здесь избыточны, но не повредят. // extern определяет функции, которые могут быть вызваны вне текущего файла, поведение по умолчанию даже без ключевого слова

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

// Файл реализации "api.c"#include  "api.h"struct  Entity  {  int  ent_id ;  // Идентификационный номер  char  ent_name [ 20 ];  // Имя  ...  и  другие  члены  ... };// Реализации функций API struct  Entity  *  open_entity ( int  id ) {  ...  }int  process_entity ( struct  Entity  * info ) {  ...  }void  close_entity ( struct  Entity  * info ) {  ...  }

Изменение имени [ править ]

Ниже приведен пример Python , который не поддерживает ограничения доступа к переменным. Однако по соглашению переменная, имя которой начинается с символа подчеркивания, должна считаться частной. [12]

class  Car :  def  __init__ ( self )  ->  None :  self . _maxspeed  =  200  def  drive ( self )  ->  None :  print ( f "Максимальная скорость { self . _maxspeed } ." ) redcar  =  Автомобиль () redcar . drive ()  # Это напечатает "Максимальная скорость 200."красный автомобиль . _maxspeed  =  10 redcar . drive ()  # Это напечатает "Максимальная скорость 10".

См. Также [ править ]

  • Наследование (объектно-ориентированное программирование)
  • Объектно-ориентированное программирование
  • Шаблон проектирования программного обеспечения
  • Образец фасада

Ссылки [ править ]

  1. ^ a b Роджерс, Wm. Пол (18 мая 2001 г.). «Инкапсуляция - это не сокрытие информации» . JavaWorld . Проверено 20 июля 2020 .
  2. Голуб, Аллен (5 сентября 2003 г.). «Почему методы Getter и Setter - зло» . Информационный мир . JavaWorld . Проверено 17 января 2021 года .
  3. ^ Пирс 2002 , § 24.2 Абстракция данных с помощью экзистенциалов
  4. ^ Скотт, Майкл Ли (2006). Прагматика языков программирования (2-е изд.). Морган Кауфманн. п. 481. ISBN. 978-0-12-633951-2. Механизмы инкапсуляции позволяют программисту группировать данные и подпрограммы, которые работают с ними, вместе в одном месте и скрывать нерелевантные детали от пользователей абстракции.
  5. ^ Дейл, Нелл Б.; Уимс, Чип (2007). Программирование и решение проблем с помощью Java (2-е изд.). Джонс и Бартлетт. п. 396. ISBN. 978-0-7637-3402-2.
  6. ^ Митчелл, Джон С. (2003). Понятия в языках программирования . Издательство Кембриджского университета. п. 522. ISBN. 978-0-521-78098-8.
  7. ^ a b Пирс, Бенджамин (2002). Типы и языки программирования . MIT Press. п. 266. ISBN. 978-0-262-16209-8.
  8. ^ Коннолли, Томас М .; Бегг, Кэролайн Э. (2005). «Глава 25: Введение в объектную DMBS § Объектно-ориентированные концепции». Системы баз данных: практический подход к проектированию, внедрению и управлению (4-е изд.). Pearson Education. п. 814. ISBN 978-0-321-21025-8.
  9. ^ Гамма, Эрих; Хелм, Ричард; Джонсон, Ральф; Влиссидес, Джон (1994). Шаблоны проектирования . Эддисон-Уэсли. ISBN 978-0-201-63361-0.
  10. Перейти ↑ King, KN (2008). Программирование на C: современный подход (PDF) (2-е изд.). WW Norton & Company. п. 464. ISBN  978-0393979503. Дата обращения 1 ноября 2019 .
  11. ^ Король, Ким Н. Программирование C: современный подход . WW Norton & Company, 2008. Гл. 18, стр. 464, ISBN 0393979504 
  12. ^ Бадер, Дэн. «Значение подчеркивания в Python» . Улучшите свои навыки Python . Дата обращения 1 ноября 2019 .