Инкапсуляция
Скрытие внутреннего устройства объектов называется инкапсуляцией и является одним из основных принципов ООП. Такой подход позволяет обезопасить внутренние данные (поля) объекта от изменений (возможно, разрушительных) со стороны других объектов; проверять корректность данных, поступающих от других объектов, повышая тем самым надежность программного кода; передавать внутреннюю структуру и код объекта любым способом, не меняя его внешние характеристики (интерфейс), и при этом никакой переделки других объектов не требуется.
По умолчанию все атрибуты и методы объекта являются открытыми. Соответственно, из основного кода программы можно использовать значения атрибутов и вызывать методы. Но для реализации инкапсуляции можно сделать атрибуты и методы класса закрытыми.
Предположим, при создании класса Student мы хотим оставить открытыми атрибуты, отвечающие за имя студента и город, в котором он проживает. Информацию о возрасте студента мы хотим сделать недоступной. Для того чтобы сделать подобный атрибут закрытым, мы начнем запись его в программе с двух
нижних подчеркиваний, например, self._vozr. В следующем коде показано, что
доступ к закрытому атрибуту внутри объявления класса может быть осуществлен очень просто. Результатом выполнения программы (листинг 157) станет вывод сообщения: «Здравствуйте, я — студент Сергей из Москвы 17».
self.name=name ^Открытые атрибуты self.city=city
self._vozr=vozr #Закрытый атрибут
рпп^»3дравствуйте, я — студент», self.name, «из», self.city, self, vozr) stl=Student(‘Ceprefi’, ‘Москвы’,’17’)
Продемонстрировать ситуацию, когда закрытие атрибута приводит к ограничению доступа к нему из основного кода, можно на следующем примере. Попытка обратиться к атрибуту vozr вне объявления класса Student (т. е. просто из командной строки) приводит к ошибке, в которой сообщается о том, что объект Student не имеет атрибута vozr (рис. 159). Такая же ошибочная ситуация возникнет даже в том случае, если указать атрибут с двумя нижними подчеркиваниями, например, print(stl._vozr).
[A Python 3.5.1 Shell

File Edit SheN Debug Options Window Help
Python 3.5.1 (v3.5.1:37aQ7cee5969, Dec 6 2015, 01:38:43) [MSC v ^ .1900 32 bit (Intel)] on Win32
Type «copyright”, «credits» or «license()» for more information.
RESTART: C:/Users/Cepren/AppData/Local/Programs/Python/Python35 -32/My_Project/verstka .py
Здравствуйте, я — студент Сергей из Москвы 17 »> stl=Student(‘Ростислав•,’Москва’,’79 1 )
Traceback (most recent call last) :
«, line 1, in print(stl.vozr)
AttributeError: ‘Student’ object has no attribute ‘vozr’
Итак, рассказав о методах создания закрытых атрибутов и способах доступа к ним, можно перейти к разговору о создании закрытых методов. Для этого дополним код методом_talk(), с помощью которого выведем сообщение: «Нач
Результат работы программы представлен на рис. 160.

Python 3.5.1 Shell File Edit Shell Debug Options Window Help
Python 3.5.1 (v3.5.1:37a07cee5969, Dec 6 2015, 01:38:43 A I
) [MSC v.1900 32 bit (Intel)] on Win32
Type «copyright”, «credits» or «license()» for more info rmation.
RESTART: C:/Users/Cepreii/AppData/Local/Programs/Python/ Python35-32/My_Project/verstka.py Здравствуйте, я — студент Сергей из Москвы 17 Начнем урок »>
Рис. 160. Результат работы программы. Вызван метод message()
После создания закрытого метода можно продемонстрировать ситуацию, когда из пользовательского кода доступ к такому методу не может быть осуществлен. В частности, обращение к классу Student с указанием метода_talk() вызо
вет исключение AttributeError с сообщением об отсутствии соответствующего атрибута (рис. 161).
Тем не менее, существует возможность вызвать закрытый метод (или получить значение скрытого атрибута), обратившись к имени класса с помощью следующего синтаксиса:
Давайте получим доступ к закрытому атрибуту в нашей программе, написав
оператор print(stl._Student_vozr), и вызовем закрытый метод, оператором
stl._Student_talk(). Подобная ситуация показана на рис. 162.

File Edit SheJI Debug Options Window Help
Python 3.5.1 (v3.5.1:37a07cee5969, Dec 6 2015, 01:33:48) [MSC v.1900 32 bit (Intel)] on Win32
Type rf copyright”, «credits» or «license () » for more information
RESTART: C:/Users/Ceprepi/AppData/Local/Program.s/Python/Python3 5-32/My_Project/verstka.py
Здравствуйте, я — студент Сергей из Москвы 17 Начнем урок
»> print (stl ._Student_vozr)

Рис. 161. Сообщение об ошибке
Рис. 162. Вызов закрытого атрибута и обращение к закрытому методу
После работы над созданием закрытых атрибутов и методов может возникнуть естественный вопрос: «А зачем их делать закрытыми, если доступ к ним все равно имеется?» Ответ можно дать такой: во-первых, случайно воспользоваться закрытым атрибутом или методом не удастся, а, во-вторых, инкапсуляция, т. е. ограничение доступа к методам или переменным, в Python существует на уровне договоренности между программистами, поэтому не стоит стремиться закрывать абсолютно все методы и атрибуты созданного класса.
Инкапсуляция
Инкапсуляция в программировании — это принцип, согласно которому внутреннее устройство сущностей нужно объединять в специальной «оболочке» и скрывать от вмешательств извне. Доступ к объектам возможен через специальные открытые методы, а напрямую обратиться к их содержимому нельзя.

«IT-специалист с нуля» наш лучший курс для старта в IT
Инкапсуляцию также описывают как принцип разделения логики и поведения. Логика — то, как что-то устроено внутри. Поведение — то, как оно взаимодействует с другими сущностями. Разделение этих двух понятий упрощает взаимодействие объектов в коде.
Обычно содержимое заключается в специальную программную оболочку, которая закрывает данные от внешних обращений. Принцип похож на автоматическую коробку передач: вам не приходится вручную управлять каждым элементом системы, более того — во время управления машиной к ним нет доступа. Есть только коробочка с рычагом, в качестве которой в программировании выступают открытые методы. Это понятно из названия: сущность оказывается «в капсуле», изолированной от внешнего мира.
Профессия / 8 месяцев
IT-специалист с нуля
Попробуйте 9 профессий за 2 месяца и выберите подходящую вам

Для чего нужна инкапсуляция
Инкапсуляция считается одним из четырех основных принципов ООП — объектно-ориентированного программирования. Этот подход представляет сущности в коде как классы и объекты, позволяет «строить» код из них, как из кирпичиков. Но чтобы объекты грамотно выполняли свои задачи и не ломались, нужна инкапсуляция.
Объяснить ее значимость поможет подход «от обратного». Вот как выглядела бы работа с кодом без инкапсуляции:
- Логика и поведение не разделяются — это значит, что если объект должен взаимодействовать с другим, ему придется учитывать его структуру;
- В любой объект можно обратиться извне напрямую — просто изменить внутреннюю переменную или сделать что-то еще;
- В результате код усложняется, а внутри объектов возникает путаница, которая может привести к ошибкам.
Поэтому инкапсуляция нужна — так код становится более упорядоченным и повышается отказоустойчивость. Ведь если сломается инкапсулированный объект, это не повлияет на работу других. Примерно как сломанная кнопка не приводит к поломке всего устройства.
Инкапсуляция, абстракция и сокрытие данных
При чем тут абстракция. Инкапсуляция тесно связана с понятием абстракции данных — одним из самых старых принципов ООП. Это понятие говорит, что любая сущность должна описываться каким-то минимумом ее возможностей. Мелкие особенности уже не важны для создания полного описания. Например, чтобы пользоваться телефоном, нам неважно, какого он цвета — с точки зрения функциональности это неважный параметр.
Абстракция помогает работать с объектами и не обращать внимания на то, как они устроены внутри. А для этого как раз нужна инкапсуляция.
Отличие от сокрытия данных. Но из определения абстракции необязательно следует сокрытие данных. Поэтому сейчас считается, что сокрытие данных от воздействий извне и инкапсуляция — немного разные вещи. Они различаются целью:
- Сокрытие нужно, чтобы обеспечить безопасность данных, и подразумевает невозможность доступа;
- Инкапсуляция нужна, чтобы обеспечить целостность объекта и дать возможность пользоваться им, не вдаваясь в подробности его реализации. При этом технический доступ к объекту в некоторых случаях может сохраниться.
Соответственно, различаются и реализации обоих принципов. Хотя тут многое зависит от языка программирования: в некоторых языках, например, 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-специалист с нуля
Наш лучший курс для старта в IT. За 2 месяца вы пробуете себя в девяти разных профессиях: мобильной и веб-разработке, тестировании, аналитике и даже Data Science — выберите подходящую и сразу освойте ее.


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

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

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

1. Откройте доступ ко всем видеоурокам комплекта.

2. Раздавайте видеоуроки в личные кабинеты ученикам.

3. Смотрите статистику просмотра видеоуроков учениками.
Получить доступ
Конспект урока «Принципы ООП: инкапсуляция»
· Использование инкапсуляции в программировании.
Инкапсуляцией называется скрытие внутреннего устройства объекта, а также объединение данных и методов для работы с ними в одном объекте. На практике это означает, что внутреннее устройство объекта скрыто от остальных. Вспомним о том, что после того, как мы провели объектно-ориентированный анализ задачи и выделили в ней основные классы объектов, мы можем поручить программирование разных классов объектов разным программистам. При этом важно, чтобы классы программировались в соответствии с интерфейсом, правилами обмена данными, которые описываются в техническом задании, – основном документе, на который ориентируется программист в процессе разработки. Практически интерфейс – это система внешних свойств и методов класса. Остальные же (внутренние) поля и методы класса должны быть скрыты от его окружения.
У этого подхода есть свои преимущества. Так можно обезопасить внутренние данные объекта от изменений со стороны других объектов, которые могут быть разрушительны. Так объект может проверять данные, которые поступают от других объектов, на корректность. Так можно как угодно изменять внутреннее устройство объекта, независимо от его внешних характеристик. Таким образом изменение одного класса объектов не влечёт за собой изменение других.
Рассмотрим пример. Допустим, что нам нужно реализовать класс, который описывает цветной круг на плоскости. Рассмотрим, как можно задать такой круг. Начнём с описания его размера. Размер круга можно описать его радиусом. Цвет круга опишем в виде символьной строки, в которой будет храниться шестнадцатеричный код его составляющих в модели RGB. Напомним, что это шестизначное шестнадцатеричное число. Первая пара его цифр – это число, означающее количество красного цвета, вторая пара – зелёного и третья – синего.

Положение круга в пространстве можно задать координатами точки его центра. Для описания этой точки опишем отдельный класс, который так и назовём – «Точка». У этого класса будет два поля – его координаты x и y, заданные вещественными числами.
Опишем наш круг. Начнём с описания класса Point, что в переводе означает «точка». Опишем конструктор этого класса. Очевидно, что у объекта этого класса будет 2 поля – его координаты x и y. По умолчанию будем размещать точку в начале отсчёта, то есть сделаем её поля равными нулю.
def __init__ (self):
Далее опишем класс Сircle, что в переводе означает «круг». Опишем конструктор этого класса. У круга будет 3 поля: радиус, который обозначим буквой R, по умолчанию он будет равен нулю; цвет – Calor, который по умолчанию будет чёрным, то есть будет описываться символьной строкой: 000000; и центр, который будет объектом класса Point. Мы закончили описание класса Circle.
def __init__ (self):
Ниже, в основной программе, создадим в переменной c объект класса Circle. Сейчас в основной программе мы можем изменять поля окружности c так, как нам заблагорассудится. Например, мы можем задать ей отрицательный радиус или же в качестве цвета произвольную символьную строку, однако такие данные не будут иметь смысла. У нас есть доступ ко всем данным объекта, так как по умолчанию они общедоступны. Это можно изменить. Имена внутренних полей, доступ к которым ограничен, должны начинаться с двойного подчёркивания. Изменим таким образом в классе Circle поля, в которых хранятся цвет и радиус круга. Теперь к этим полям могут обращаться лишь методы этого класса, за пределами класса обратиться к ним нельзя.
def __init__ (self):
Попробуем в основной программе вывести на экран значение поля __R у объекта c. Сохраним описанный модуль и запустим его на выполнение. Программа вывела сообщение о том, что у объектов класса Circle нет таких атрибутов.
Однако иногда нам нужно прочитать значение внутреннего поля объекта или даже изменить его. Для этого в классе могут быть описаны методы доступа к этим полям. На жаргоне программистов их называют «гетеры» и «сетеры», сейчас вы поймёте почему. Название метода, возвращающего значение поля, обычно состоит из слова «get», что в переводе означает «получить», и имени поля. Название же метода для изменения значения поля обычно состоит из слова «set», что в переводе означает «задать», и имени поля. При этом методу-сетеру в качестве аргумента задаётся новое значение поля. Необязательно использовать именно эти имена методов, просто они являются традиционными в большинстве языков программирования.
Опишем эти методы для поля __R. Начнём с метода getR. В этом методе достаточно написать инструкцию возврата значения соответствующего поля. Этот метод общедоступен, поэтому его можно вызвать в любом месте программы, и при этом он описан в классе Circle, а значит имеет доступ ко всем его полям. Теперь опишем метод для изменения радиуса круга setR. Помимо обычного параметра self у него будет ещё один параметр, назовём его value, что переводится как «значение». В этом методе просто присвоим внутреннему полю __R значение параметра value.
def __getR (self):
def __setR (self, value):
Теперь в основной программе перед тем, как вывести на экран значение радиуса окружности c, установим его равным 3. Сохраним изменения в модуле и запустим его на выполнение. Теперь на экран было выведено число 3, то есть то самое значение, которое мы задали радиусу окружности. Программа работает правильно.
И здесь у вас мог возникнуть вопрос: «А в чём смысл того, что мы сделали?» Ведь несмотря на то, что поле __R стало внутренним, мы всё равно можем изменять его значение так, как захотим с помощью методов доступа. Дело в том, что мы можем описать любую логику работы методов доступа, какую только захотим. Например, мы можем изменить метод setR, добавив в него защиту от некорректных данных. Вначале опишем в методе обработчик исключений, в нём запишем ветвление с условием, что результат функции float (value) >= 0. Если это условие выполняется, то присвоим полю R это значение. Если условие ветвления ложно или же этот код вернёт любое исключение, то ничего делать не будем.
def __setR (self, value):
if float (value) >= 0:
self.__R = float (value)
Таким образом метод setR изменит значение поля R лишь в том случае, если его параметром будет неотрицательное число, в противном случае ничего не произойдёт. Проверим это. Уберём описание основной программы, оставив в модуле только описанные классы. Сохраним изменённый модуль и запустим его на выполнение. В интерактивном режиме среды разработки создадим объект c класса Circle, с помощью метода setR попробуем сделать его радиус отрицательным. Теперь просмотрим значение радиуса окружности c, вызвав у неё метод getR. Радиус окружности всё ещё равен нулю. Теперь попробуем сделать радиус c равным 7.5 и снова просмотрим его значение. На этот раз оно изменилось. Теперь круг c не принимает некорректный радиус.
Однако предположим, что у нас уже есть программы, которые ранее обращались к полю R некоторых объектов класса Circle, но теперь мы сделали его закрытым, тем самым изменив интерфейс класса. Неужели теперь придётся вносить правки во все эти программы? Не придётся, и в этом нам поможет такая вещь, как свойство – способ доступа к внутреннему состоянию объекта, имитирующий обращение к его внутреннему полю.
Посмотрим, как это работает. Для этого в классе Circle за пределами методов объявим переменную с именем R без подчёркиваний и присвоим ей некоторое значение. После знака равенства запишем слово property, что в переводе означает «cвойство», и после него в скобках, через запятую, укажем методы для чтения и записи значения этого свойства, то есть getR и setR.
R = property (__getR, __setR)
Сохраним изменения в модуле и запустим его на выполнение. Снова создадим объект c класса Circle. Изменим его радиус, обратившись к полю R. Попытаемся присвоить ему значение произвольной символьной строки. Теперь просмотрим его значение. Радиус всё ещё начальный, то есть равен нулю. Теперь попробуем присвоить ему значение 5, и снова просмотрим его. Теперь радиус изменился. Интерфейс обращения к полю радиуса стал прежним.
Теперь мы можем сделать закрытыми методы доступа к радиусу окружности. Они будут доступны из открытого свойства R. Теперь изменим доступ к остальным полям класса. Для изменения поля Color опишем внутренний метод __setColor с параметром value. В нём проверим, действительно ли value содержит шестизначное шестнадцатеричное число. Для этого запишем обработчик исключений, в котором запишем ветвление с условием, что длина символьной строки value равна 6. Если это условие выполняется, попробуем полю __Color присвоить значение функции int (value, 16), в которой в качестве второго параметра указано основание системы счисления. Эта функция преобразует значение в шестнадцатеричное целое число. Если при попытке преобразования возникнет исключение, то ничего делать не будем. Опишем внутренний метод __getColor, который будет возвращать значение внутреннего поля __Color, преобразованного в символьную строку с помощью метода format. Строка формата для этого метода будет содержать символы: . Она означает, что нужно вывести шестнадцатеричное число в шесть знаковых позиций, причём свободные позиции слева нужно заполнить нулями. Теперь опишем общедоступное свойство Color с методами доступа __getColor и __setColor.
def __setColour (self, value):
if len (str (value)) == 6:
self.__Colour = int (value, 16)
def __getColour (self):
return ».format (self.__Colour)
Colour = property (__getColour, __setColour)
Теперь обезопасим изменение центра окружности. Для этого не будем ничего изменять в классе Circle. Вместо этого в классе Point сделаем поля x и y внутренними и опишем для них внутренние методы доступа. После этого опишем свойства x и y, в которых перечислим соответствующие методы доступа.
def __init__ (self):
def __getX (self):
def __setX (self, value):
ЗНАКОМСТВО С ЯЗЫКОМ
Понятие объекта является ключевым в современном программировании.
Идея объекта очень проста рассматривать данные и функции, которые эти данные обрабатывают, как одно целое.
понятие объекта
Объект это единая конструкция, содержащая в себе набор данных и функций или, в терминологии JavaScript, набор свойств и методов.
| функция = метод |
| переменная = свойство |
инкапсуляция
Этим термином обозначают скрытие внутреннего устройства объекта. Объект рассматривается как черный ящик. Известны свойства объекта, то есть доступные извне переменные. Известны методы объекта, то есть доступные извне функции. Но как устроены эти функции, по каким алгоритмам они работают, программисту не сообщается.
Программист, пользователь объекта, не знает и о том, есть ли у объекта дополнительные внутренние вспомогательные функции и переменные и как они связаны с доступными свойствами и методами.
Вот телевизор это сложное устройство. Но зачем пользователю знать, что внутри этого объекта? Достаточно уметь нажимать кнопки на пульте, чтобы заставить ящик показывать нужную программу с подходящей громкостью.
Инкапсуляция удобна, правда? Она позволяет слабому человеческому разуму справиться с огромными информационными потоками, закрывая глаза на несущественные детали.
Кто-то делает микросхемы, кто-то собирает из них телевизор, кто-то смотрит программу Время. И все довольны. Каждый хорошо знает свое дело. Представьте, что для просмотра телевизора необходимо было бы знать в деталях устройство этих паукообразных штук, которые называют микросхемами, а также технологию изготовления люминесцентных трубок и все такое прочее.
объект и экземпляр объекта
Вообще говоря, конкретный телевизор это, в терминологии JavaScript, не объект, а экземпляр объекта. Объектом является комплект документации, по которой на заводе изготовляется продукция. Все телевизоры, которые сходят с конвейера, имеют одни и те же свойства изображения и одни и те же методы управления этими свойствами.
То же и в программировании. Объект это шаблон, документация. Экземпляр объекта это рабочая копия.
интерфейс объекта и внутреннее устройство объекта
Программист Сидоров придумал новый объект Rectangle . Он сообщил коллегам следующую информацию.
| Объект Rectangle | |
|---|---|
var x = new Rectangle(a,b);
Когда экземпляр объекта создан, можно использовать следующие методы и свойства:
| свойства | описание |
|---|---|
| width | Ширина прямоугольника |
| height | Высота прямоугольника |
| методы | описание |
|---|---|
| square() | Площадь прямоугольника |
| perimeter() | Периметр прямоугольника |
| radius() | Радиус описанной окружности |
var x = new Rectangle(3,4); // Вычисление площади. var s = x.square(); // Вычисление периметра. var p = x.perimeter(); // Вычисление радиуса описанной окружности. var r = x.radius(); // Вычисление максимального размера. var m = x.width; if (x.height > m) m = x.height
Что сообщил Сидоров коллегам? Он сообщил интерфейс своего объекта, то есть информацию, необходимую для взаимодействия с объектом.
Сидоров не показал друзьям программные коды функций square , perimeter , radius . Не сказал он и о вспомогательной функции sqrt , которая была написана для вычисления квадратного корня (эту функцию использует у Сидорова метод radius ). Не сказал Сидоров и про переменную temp , которая потребовалась объекту для промежуточных вычислений.
Другими словами, Сидоров не показал внутреннее устройство своего объекта. Да и зачем коллегам знать это? Сидоров программист хороший, все свои коды тщательно проверяет, значит, можно пользоваться только интерфейсом, не заглядывая к Сидорову на кухню.
Интерфейс объекта это доступные для использования переменные и функции объекта.
Внутреннее устройство объекта это описание переменных и функций внутри объекта на языке программирования (кухня Сидорова).
Аналогия с телевизором: интерфейс это пульт управления. Внутреннее устройство это электронные потроха в ящике.
встроенные объекты и объекты пользователя
В языке JavaScript много встроенных объектов. Их не надо программировать, они заложены в сам язык. Это означает, что коды этих объектов входят в состав программных кодов браузера. Программист должен знать интерфейсы этих объектов, уметь создавать экземпляры, и тогда он сможет использовать встроенные объекты по своему усмотрению.
JavaScript позволяет программировать новые объекты и менять алгоритм работы встроенных. Это очень удобно и привлекательно для программиста. Далее в книге будет много примеров на эту тему, но сначала рассмотрим работу нескольких встроенных объектов (более подробный список приводится в справочном разделе в конце книги).
объект Date
Начнем практическое рассмотрение встроенных объектов языка JavaScript с очень полезного объекта Date . Этот объект используется для работы с датой и временем.
Для создания экземпляра объекта (не только объекта Date, но и любого другого) в языке JavaScript используется ключевое слово new :
var now = new Date();
Теперь переменная now является экземпляром объекта Date и содержит текущую дату и время.
В общем случае экземпляр образуется следующим образом:
var переменная = new Date(параметры);
Возможно указание следующих параметров:
var now = new Date();
var birthday = new Date(1954,1,8);
var bell = new Date(2003,0,14,12,20,0);
После того, как экземпляр объекта Date создан, можно узнать, записанные в нем данные, а можно их и менять. Для этого существуют многочисленные методы, список которых приводится в справочнике.
Имя метода объекта (вспомним, что метод в терминологии JavaScript это функция) отделяется от имени экземпляра точкой.
var year = bell.getYear();
Переменная year получит значение 2003.
Рассмотрим несколько простых скриптов с объектом Date .
текущая дата и время
<SCRIPT language=JavaScript> var now = new Date(); alert("Сегодн\я: "+now.getDate()+"/"+(now.getMonth()+1)+"/"+ now.getYear()+"\n"+ "Сейчас: "+now.getHours()+":"+now.getMinutes()); //--> SCRIPT>
число дней с начала года
<SCRIPT language=JavaScript> var now = new Date(); // Начало текущего года. var begin = new Date(now.getYear(),0,1); // Число миллисекунд от начала года. var d = now.getTime() - begin.getTime(); // Число миллисекунд в дне. var msPerDay = 24*60*60*1000; // Поделим на количество миллисекунд в сутках. d /= msPerDay; // Покажем результат. alert("Прошло " + Math.floor(d) + " дней с начала года"); //--> SCRIPT>
Замечание о записи Math.floor(x). Встроенный объект Math предлагает различные математические функции и константы. Особенность этого объекта в том, что он существует в единственном экземпляре, который имеет то же имя Math . Программист не может создавать новые экземпляры этого объекта. Правда, в этом и нет необходимости. Метод floor(x) объекта Math возвращает ближайшее целое число, меньшее или равное аргументу (смотрите методы и свойства объекта Math в справочнике).
объект Array
Этот объект предназначен создания массивов данных. Массив это упорядоченный набор элементов. Доступ к отдельному элементу производится по имени и индексу (номеру). Нумерация элементов в JavaScript начинается с нуля.
пример: массив названий дней недели
dayNames = new Array("воскресенье", "понедельник", "вторник", "среда", "четверг", "пятница", "суббота");
Для доступа к отдельным элементам массива используют конструкцию:
имя_массива[индекс]
пример: показ текущей даты и времени
<SCRIPT language=JavaScript> var monthNames = new Array("\январ\я", "феврал\я", "марта", "апрел\я", "ма\я", "июн\я", "июл\я", "августа", "сент\ябр\я", "окт\ябр\я", "но\ябр\я", "декабр\я"); // Название дней недели. var dayNames = new Array("воскресенье", "понедельник", "вторник", "среда", "четверг", "п\ятница", "суббота"); // Текущая дата и время. var toDay = new Date(); // Формирование строки вывода. var str = "Cегодня: "; // Добавим в строку день месяца. str += toDay.getDate() + " "; // Добавим в строку название месяца. str += monthNames[toDay.getMonth()] + " "; // Добавим в строку год. str += toDay.getYear() + " года, "; // Добавим день недели. str += dayNames[toDay.GetDay()] + "\n"; // Добавим время. str += "Сейчас: " + toDay.getHours() + ":" + toDay.getMinutes() + ":" + toDay.getSeconds(); // Покажем строку. alert(str); //--> SCRIPT>
Длина массива (число элементов в нем) может меняться во время работы программы:
var f = new Array(); // Сейчас массив пуст. f[0] = 1; // В массиве один элемент. f[1] = 1; // В массиве два элемента. f[2] = f[0]+f[1]; // В массиве три элемента. f[5] = 8; // В массиве шесть элементов f[0]. f[5].
пример: максимальный элемент массива
Замечание. Два цикла рассмотренного примера можно объединить в один:
var max = a; for(i=0; iif(set[i] > max) max = set[i]; >
До сих пор мы пользовались методами объектов и еще ни разу их свойствами.
Вспомним, что свойства объекта это, в терминологии JavaScript, те интерфейсные переменные, которые доступны пользователю объекта.
На самом деле, конечно, речь не об объекте, а о конкретном экземпляре объекта. Для обращения к свойствам указывается имя экземпляра объекта и через точку имя свойства, например:
<SCRIPT language=JavaScript> var set = new Array("Горбунков", "Семен", "Семенович"); alert (set.length); //--> SCRIPT>
Свойство length содержит число элементов массива его длину.
Язык JavaScript допускает много вольностей при обращении с объектами. Так, например, можно задать экземпляр массива без ключевого слова new и имени объекта Array :
var set = [1, 4, 9, 16, 25, 36];
Конечно, браузер, просматривая такую запись, все равно создает экземпляр объекта Array, точно такой же, как и при записи:
var set = new Array(1, 4, 9, 16, 25, 36);
В предыдущих уроках мы часто строили экземпляры объекта String , даже не подозревая об этом. Такая запись:
var title = "Старик, упавший с каланчи";
совершенно эквивалентна записи:
var title = new String("Старик, упавший с каланчи");
Для работы со встроенными объектами JavaScript удобно иметь под рукой справочник. Он приводится в конце этой книги.
Ниже располагаются ссылки на описание свойств и методов встроенных объектов в этом справочнике:
Нажмите кнопку Сброс , затем выберите верные ответы на вопросы.
Нажмите кнопку Сброс , затем приступайте к решению.