Initial commit from the 2013 with minor fixes. From now and then,
[perlbook.git] / s05.tex
blob62986c938129789df74ea5f559b150fa9af4f48c
1 \section{Карп в пакете}
3 Защищенность и модульность — два важнейших принципа программирования. В
4 перл они реализуются (в том числе) с помощью пакетов. Каждый пакет —
5 независимый фрагмент программы, у которого своя область имён. Область
6 имён --- это часть программы со своей областью видимости глобальных
7 идентификаторов. Другими словами, у пакета своя атмосфера. Это
8 гарантирует, что код в пакете не смешается с переменными и подпрограммами
9 другого фрагмента.
11 Пакет можно разместить в отдельном файле, разбить на несколько файлов.
12 Или наоборот, несколько пакетов могут делить один файл.
14 Кроме пакетов, в обиходе программиста есть ещё модули. Модули — это
15 пакеты, организованные специальным образом, чтоб их можно было загружать
16 и интегрировать с конкретной программой.
18 Создание модуля — серьезный шаг, сделать который могут только серьезные
19 ребята. Как минимум, предполагается, что модуль будет использоваться
20 часто. Вступая на территорию модулей, мы попадаем в самое сердце
21 сообщества программистов на Perl — CPAN. И тут нужны опыт и смекалка. Особое
22 внимание нужно уделить интерфейсу, ведь кривой интерфейс отпугнёт
23 потенциальных пользователей. Им будет легче написать свою реализацию. Но
24 об этом потом. Итак, пакеты:
26 \perl{l50.pl}
28 Данный код надобно разместить в отдельном файле \remph{coolstuff.pm} и сохранить в
29 один каталог со скриптом, который будет его использовать.
31 В первой строке мы объявляем, что будем работать в пространстве имён
32 \emph{coolstuff} . \emph{BEGIN} и \emph{END} — специальные функции, конструктор и деструктор
33 пакета соответственно. Первая вызывается при входе в пространство имён
34 пакета, вторая --- при выходе из него. Вызывает их интерпретатор и только
35 он, программист не может вызвать эти спец. функции самостоятельно. Служат
36 они, например, для инициализации переменных, выделения/освобождения
37 памяти и других утилитарных потребностей.
39 \emph{\_\_PACKAGE\_\_} — специальная переменная, содержащая имя текущего пакета.
41 \emph{AUTOLOAD} является спец. функцией и вызывается всякий раз, когда скрипт
42 запрашивает из пакета подпрограмму, которой в нём нет. В скаляре \$AUTOLOAD
43 хранится имя запрошенной подпрограммы. Если не определить метод AUTOLOAD,
44 выполнение скрипта завершится с сообщением об ошибке при попытке
45 вызывать несуществующую функцию.
47 \remph{return} из 8 строки должен вернуть в скрипт истинное значение, что будет
48 сигнализировать о том, что пакет/модуль успешно подключен.
50 А вот так мы будем использовать наш пакет в скрипте:
52 \perl{l51.pl}
54 Пакеты и модули можно подключать директивами do, require и use. Первые две
55 подключают пакеты/модули на этапе выполнения, последняя на этапе
56 компиляции. Это означает, что do и require должны подключить модуль до его
57 использования в программе. При этом, между do и require лучше выбрать require, т.к.
58 данная директива не подключает повторно уже загруженные модули. Да что уж
59 там! Я вообще никогда не видел, чтоб кто-то подключал пакеты/модули
60 директивой „do”.
62 Обратите внимание на то, как мы используем методы пакета. Сначала идёт
63 разыменовывающий префикс (если забыли, то для подпрограмм это амперсанд),
64 затем мы говорим, в какой области видимости искать нужные нам вещи, после
65 идёт оператор :: и имя искомого функционала.
67 Любые переменные, не объявленные с ключевым словом my, ассоциируются с
68 пакетом. По умолчанию наш карп находится в пакете main.
70 Но каждый раз писать полное имя вида \remph{имя\_пакета::имя\_подпрограммы}
71 дело неблагодарное. Поэтому давайте попробуем экспортировать часть
72 содержимого пакета в текущую область глобальных имён (умно звучит, да?)
74 \perl{l52.pl}
76 Теперь можно вызывать подпрограмму просто указав её имя:
78 \perl{l53.pl}
80 Как видите, нам наконец-то пригодился конструктор. Exporter нужен, чтоб при
81 загрузке пакета/модуля, его содержимое экспортировалось в область
82 глобальных имён скрипта. Про массив @ISA поговорим позже. А может, совсем
83 говорить не будем, сейчас гораздо важнее обратить внимание на массив
84 @EXPORT. В нём перечисляются вещи, которые будут „видны” из основного
85 скрипта. Экспортировать имена скаляров, вообще-то, плохая идея. Почему?
86 Существует такое понятие, как инкапсуляция. Это --- один из 4х китов, на
87 которых стоит ООП. Суть в том, что данные (в нашем случае, например,
88 скаляры) хранятся внутри объекта и недоступны извне. Изменять данные
89 можно только путём вызова публичные методы самого объекта. Это избавляет
90 от множества проблем:
92 \perl{l54.pl}
94 Код пакета:
96 \perl{l55.pl}
98 Теперь у нас есть внутренняя переменная-счётчик, скрытая внутри пакета.
99 Изменяем мы её с помощью публичных методов самого пакета. Тем не менее,
100 скаляр \$counter по-прежнему доступен из скрипта по полному имени:
102 \begin{verbatim}
103 $mycounter::counter;
104 \end{verbatim}
106 Чтоб скрыть \$mycounter окончательно, нужно объявить его с ключевым
107 словом \remph{my}.
109 Прежде, чем идти дальше, нужно разобраться с областями видимости и
110 ключевыми словами: \emph{my}, \emph{our}, \emph{local}.
112 \subsection{Область видимости}
114 \begin{em}
115 ,,Дурак дурака видит издалека''
116 \begin{flushright}
117 -Народная мудрость
118 \end{flushright}
119 \end{em}
121 Говоря о защищенности и модульности, нельзя обойтись без понимания
122 области видимости. Область видимости --- это пространство имён, в котором
123 существует наша переменная. Определение очень грубое, но нам сгодится.
124 Переменную\footnote{Скаляр, массив или хэш} в Perl можно объявить по-разному.
125 Ключевое слово \remph{our} объявляет глобальную переменную. Такие переменные
126 видны из любой точки пакета, в том числе в подпрограммах, в пакете
127 объявленных. По умолчанию, скрипт работает с пакетом \emph{main} .
128 Использование глобальных переменных --- плохая идея по ряду причин.
129 Изменение значения глобальной переменной внутри одной из подпрограмм
130 может сильно испортить жизнь программисту:
132 \perl{l56.pl}
134 Данный пример показывает ещё один недостаток. Подпрограмма
135 \emph{tell\_the\_truth} оказалась прибита гвоздями к скрипту, и её
136 невозможно будет использовать в других проектах.
138 Спецификатор „local” позволяет объявлять локальные копии глобальных
139 переменных и предыдущий пример мог бы быть переписан так:
141 \perl{l57.pl}
143 Подпрограмма по-прежнему прибита к скрипту, но мир таки стал немного
144 лучше. Теперь мы не меняем глобальную переменную в недрах функции,
145 изменения коснутся только локальной копии с тем же именем, значение
146 которой, как последнее вычисленное значение, будет возвращено из
147 подпрограммы. Напомню, что \remph{v10} означает
148 \remph{символ с кодом десять} , что соответствует символу перевода
149 строки.
151 %grammar check
152 Любознательный читатель спросит: "А как же быть, если нужно вернуть из
153 функции несколько значений?! Вот тут-то глобальные переменные и
154 пригодятся, нет?". Конечно, нет! Для подобных трюков есть ссылки. Но
155 всё не так плохо. Ведь, если звезды зажигают - значит - это кому-нибудь
156 нужно?
158 Старое-доброе ключевое слово \remph{my} позволяет объявлять переменные с
159 лексической областью видимости. Таким образом, объявляются самые закрытые
160 и аскетичные типы переменных. Такие переменные видны только внутри
161 блока, в котором они объявлены, и во вложенных в этот блок блоках.
163 \perl{l58.pl}
165 Скаляр \$text виден внутри подпрограмм fix\_register и fix\_smiles, так как
166 они объявлены в одной с \$text области видимости.
168 \subsection{Модули}
170 Как мы уже говорили, пакет --- это гетто для переменных, чтоб их никто не
171 трогал извне. Модуль --- это тоже пакет, но оформленный в виде отдельного
172 файла с расширением \emph{.pm} . Имя модуля и файл, в котором он находится,
173 должны совпадать и, вроде как, существует договорённость, что имя модуля
174 должно начинаться с заглавной буквы.
176 Подключаются модули так же, как и пакеты. Кстати, если вы написали
177 проект, использующий несколько модулей, для удобства раскидав модули
178 по каталогам, то вот способ, как подключить модуль из каталога
179 foo\textbackslash bar\textbackslash :
181 \begin{verbatim}
182 use foo::bar::MyModule;
183 \end{verbatim}
185 По умолчанию предполагается, что модуль находится в файле с расширением
186 \emph{.pm} , поэтому расширение можно (и нужно) опустить.