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



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

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

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

 

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

Однако в Python инкапсуляция работает лишь на уровне соглашения между программистами о том, какие атрибуты являются общедоступными, а какие — внутренними.

Одиночное подчеркивание в начале имени атрибута говорит о том, что переменная или метод не предназначен для использования вне методов класса, однако атрибут доступен по этому имени.

class A:

def _private(self):

   print("Это приватный метод!")

 

>>> a = A()

>>> a._private()

Это приватный метод!

Двойное подчеркивание в начале имени атрибута даёт большую защиту: атрибут становится недоступным по этому имени.

>>> class B:

... def __private(self):

...    print("Это приватный метод!")

...

>>> b = B()

>>> b.__private()

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

AttributeError: 'B' object has no attribute '__private'

Однако полностью это не защищает, так как атрибут всё равно остаётся доступным под именем _ИмяКласса__ИмяАтрибута:

>>> b._B__private()

Это приватный метод!

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

Python не имеет инкапсуляция? (ред. с англ.)

Часть общей мудрости среди некоторых ОО фанатиков является то, что Python не является реальным ОО язык, потому что он "не имеет инкапсуляцию." Есть несколько различных вещей, которые могли бы означать, но ни один из них не говорят ничего полезного.

Python облегчает и способствует группирования данных вместе с методами, которые работают над этими данными, в том же образом, Smalltalk, C ++, и их потомки делают (и эквивалентным образом к тому, что другие OO парадигм как прототипы Self-стиле). Это действительно полезно только определение термина "инкапсуляция", и в этом смысле, Python имеет герметизацию.

Тот факт, что идиомы в Python не поощряет геттеры и сеттеры не имеет никакого значения, потому что получатели и установщики просто обеспечивают иной способ доступа к атрибутам правописание, и тот, который (за исключением случая синтаксически ограниченных языков, таких как C ++) не добавляет гибкости, future- теплоизолирующие и другие преимущества.

Тот факт, что _-приставка идиомы в Python фактически не скрыть или защитить частные переменные верно, но то же самое верно для почти всех других языках парадигмы ОО. Так что, если вы хотите определить инкапсуляцию в этих терминах, то нет, Python не является хорошим инкапсулирующий OO языка и ни один не Smalltalk, C #, Ruby, JavaScript, ...

Интерфейсы и реализации

Интерфейсы

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

Закрытые данные

Для того чтобы скрытие данных произошло, все атрибуты должны быть объявлены как private. Поэтому атрибуты никогда не являются частью интерфейсов. Частью интерфей­сов классов могут быть только открытые методы. Объявление атрибута как public на­рушает концепцию скрытия данных.

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

· способ создать экземпляр объекта Square;

· способ отправить значение объекту и получить в ответ квадрат соответствующего числа.

Как уже отмечалось ранее, если пользователю потребуется доступ к атрибуту, то будет сгенерирован метод для возврата значения этого атрибута (гет­тер). Если затем пользователю понадобится получить значение атрибута, то будет вызван метод для возврата его значения. Таким образом, объект, содержащий атри­бут, будет управлять доступом к нему. Это жизненно важно, особенно в плане безопасности, тестирования и сопровождения. Если вы контролируете доступ к атрибу­ту, то при возникновении проблемы вам не придется беспокоиться об отслеживании каждого фрагмента кода, который мог бы изменить значение соответствующего атрибута — оно может быть изменено только в одном месте (с помощью сеттера).

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

Реализации

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

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


Дата добавления: 2020-01-07; просмотров: 206; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!