Анимация
JavaScript
|
Главная Библионтека Классы, объекты и связи Яо всему миру я призываю массы на борьбу с классами. Уильям Гладстон, речь в Ливерпуле, 28 июня 1886 г. Введение Наряду со ссылками и модулями в Perl версии 5.000 появились объекты. Как обычно, Perl не заставляет всех использовать единственно правильный стиль, а поддерживает несколько разных стилей. Благодаря этому люди решают свои задачи так, как им нравится. При написании программ необязательно пользоваться объектами, в отличие от языка Java, где программы представляют собой экземпляры объектов. Однако при желании можно написать Perl-программу, в которой используется практически весь арсенал приемов объектно-ориентированного программирования. В Perl поддерживаются классы и объекты, одиночное и множественное наследование, методы экземпляров и методы классов, переопределение методов, конструкторы и деструкторы, перегрузка операторов, методы-посредники с автозагрузкой, делегирование, иерархия объектов и два уровня сборки мусора. Вы можете выбрать ровно столько объектно-ориентированных принципов, сколько захочется. Связи (ties) являются единственной частью Perl, где объектно-ориентированный подход обязателен. Но даже здесь об этом должен знать лишь программист, занимающийся реализацией модуля; случайный пользователь остается в блаженном неведении относительно внутренних механизмов. Связи, рассматриваемые в рецепте 13.14, позволяют организовать прозрачный перехват обращений к переменной. Например, с помощью связей можно создать хэш с возможностью поиска по ключу или по значению. Под капотом Если спросить десятерых программистов, что такое «объектная ориентация», вы получите десять разных ответов. Люди рассуждают об «абстракции» и «инкапсуляции», пытаются выделить основные черты объектно-ориентированных языков программирования и придумать для них умные термины, чтобы потом писать статьи и книги. Не все объектно-ориентированные языки обладают одинаковыми возможностями, но все они считаются объектно-ориентированными. Конечно, в результате появляются все новые статьи и книги. Мы будем использовать терминологию из документации Perl и страницы руководства/?ег/ой/(1). Объект представляет собой переменную, принадлежащую к некоторому классу. Методами называются функции, ассоциируемые с классом или объектом. В Perl класс представляет co6oii пакет - а обычно и модуль. Объект является ссылкой на что-то, что было приведено (blessed) к классу. Приведение ассоциирует субъект с классом. Для этого используется функция bless, вызываемая с одним или двумя аргументами. Первым аргументом является ссылка на приводимый объект, а необязательным вторым аргументом - пакет, к которому осуществляется приведение. Sobject = {}, # Ссылка на хэш bless($object, "Data.:Encoder"); tt Привести Sobject к классу tt Data. - Encoder bless($object); tt Привести Sobject к текущему пакету Имя класса соответствует имени пакета (Data::Encoder в приведенном выше примере). Поскольку классы являются модулями (обычно), код класса Data:;Encoder находится в файле Data/Encoder.pm. Структура каталогов, как и для традиционных модулей, существует исключительно для удобства; она никак не связана с наследованием, ограничением доступа к переменным или чем-нибудь еще. Однако в отличие от традиционных модулей, объектные модули очень редко используют Exporter. Вся работа должна вестись только через вызовы методов, но не через импортированные функции или переменные. После приведения объекта вызов функции ref для ссылки на него возвращает имя класса вместо фундаментального типа суб,ъекта; $оЬ] = [3,5]; print ref($obj), " ", $obj->[1], "\n"; bless($obj, "Human: Cannibal"); print ref($obj), " ", $obj->[1], "\n"; ARRAY 5 Human::Cannibal 5 Как видите, приведенную ссылку все еще можно разыменовать. Чаще всего об-ьекты реализуются с помощью приведенных ссылок на хэши. Вы можете использовать любые типы ссылок, но ссылки на хэш обеспечивают максимальную гибкость. Они позволяют создавать в объекте поля данных с произвольными именами; $ob]->{Stomach} = "Empty"; tt Прямое обращение к данным объекта $ob]->{NAME} = "Thag"; tt Символы верхнего регистра в имени поля # помогают выделить его (необязательно) Хотя Perl позволяет любому коду за пределами класса напрямую обращаться к данным объекта, это считается нежелательным. Согласно общепринятому мне- нию, работа с данными должна вестись только с использованием методов, предназначенных для этой цели. У разработчика класса появляется возможность изменить его реализацию без модификации всего кода приложений, использующих данный класс. Методы Для вызова методов используется оператор, оператор ->. В следующем примере мы вызываем метод encode() объекта Sobject с аргументом "data" и сохраняем возвращаемое значение в переменной $encoded: Sencoded = $ob]ect->encode("data); Перед нами метод объекта, поскольку мы вызываем метод конкретного объекта. Также существуют методы классов, то есть методы, вызываемые по имени класса: Sencoded = Data::Encoder->encode("data"); При вызове метода вызывается функция соответствующего класса с неявной передачей в качестве аргумента либо ссылки (для метода объекта), либо строки (для метода класса). В рецепте 13.17 показано, как вызывать методы с именами, определяемыми во время выполнения. В больщинстве гслассов существуют специальные методы, возвращающие новые объекты - конструкторы. В отличие от некоторых объектно-ориентированных языков, конструкторы Perl не имеют специальных имен. В сущности, конструктор можно назвать, как вам захочется. Программисты С++ обожают присваивать своим конструкторам в Perl имя new. Мы рекомендуем выбирать имя конструктора так, чтобы оно имело смысл в контексте решаемой задачи. Например, конструкторы расширения Тк в Perl называются по именам создаваемых ими элементов (widgets). Менее распространеннйй подход загслючается в экспортировании функции, имя которой совпадает с именем класса; см. пример в разделе «Пример. Перегруженный класс StrNum» в рецепте 13.14. Типичный конструктор выглядит следующим образом: sub new { my Sclass = shift, my Sself = {}; # Выделить новый хэш для объекта bless(Sself, Sclass), return Sself; Вызов конструктора выглядит так: Sobject = Class->new(); Если дело обходится без наследования или иных выкрутасов, это фактически эквивалентно Sobject = Class::new("Class"), Первым аргументом функции new() является имя 1сласса, к которому приводится новая ссылка. Конструктор должен передать эту строку bless() в качестве второго аргумента. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 [ 144 ] 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |