Анимация
JavaScript
|
Главная Библионтека > Смотри также- Раздел «Garbage Collection* perlobj(i). 13.14. Перегрузка операторов Проблема Вы хотите использовать знакомые операторы (например, == или +) с объектами написанного вами класса или определить интерполированное значение для вывода объектов. Решение Воспользуйтесь директивой use overload. Ниже приведены два самых распространенных и часто перегружаемых оператора: use overload (<=> => \&threeway compare); sub threeway compare { my ($s1, $s2) = @ ; uc(Ss1->{NAME}) cmp uc($s2->{NAME}); use overload ( => \&stringify ); sub stringify { my Sself = shift; return sprintf "%s (%05d)", ucfirst(lc(Sself->{NAME})), Sself->{IONUM}; Комментарий При работе со встроенными типами используются некоторые операторы (например, оператор + выполняет сложение, а . - конкатенацию строк). Директива use overload позволяет перегрузить эти операторы так, чтобы для ваших собственных объектов они делали что-то особенное. Директиве передается список пар «оператор/функция»: package TimeNumber; use overload + => \&my plus. # $ring->delete value( Svalue ) : удалить узел по значению sub delete value { my (Sring, Svalue) = @ ; my Snode = Sring->search($value); return if Snode == $ring->{OUMMY>; Sring->delete node($node); 13,14. Перегрузка операторов 483 - => \&my minus, •• => \&my star, V => \&iiiy slash; Теперь эти операторы можно использовать с объектами класса TimeNumber, и при этом будут вызываться указанные функции. Функции могут делать все, что вам захочется. Приведем простой пример перегрузки + для работы с объектом, содержащим количество часов, минут и секунд. Предполагается, что оба операнда принадлежат к классу, имеющему метод new, который может вызываться в качестве метода объекта, и что структура состоит из перечисленных ниже имен: sub iiiy plus { iiiy($left, $right) = @ ; my Sanswer = $left->new(); $answer->{SECONDS} = $left->{SECONDS} + $right->{SECONDS}; $answer->{MINUTES} = $left->{MINUTES> + $right->{MINUTES}: $answer->{HOURS} = $left->{HOURS} + $right->{HOURS>; if ($answer->{SECONDS} >= 60) { $answer->{SECONDS} %= 60; $answer->{MINUTES} ++; If ($answer->{MINUTES} >= 60) { $answer->{MINUTES} %= 60; $answer->{HOURS} ++; return Sanswer; Числовые операторы рекомендуется перегружать лищь в том случае, если объекты соответствуют какой-то числовой конструкции - например, комплексным числам или числам с повыщенной точностью, векторам или матрицам. В противном случае программа становится слишком сложной, а пользователи делают неверные предположения относительно работы операторов. Представьте себе класс, который моделирует страну. Если вы создадите оператор для сложения двух стран, то почему нельзя заняться вычитанием? Как видите, перегрузка операторов для нечисловых математических объектов быстро приводит к абсурду. Объекты (а в сущности, и любые ссылки) можно сравнивать с помощью == и eq, но в этом случае вы узнаете лишь о совпадении их адресов (при этом == работает примерно в 10 раз быстрее, чем eq). Поскольку объект является всего лишь высокоуровневым представлением обычного мащинного адреса, во многих ситуациях требуется определить собственный критерий того, что следует понимать под равенством двух объектов. Даже для нечисловых классов особенно часто перегружаются два оператора: сравнения и строковой интерполяции. Допускается перегрузка как оператора <=>, так и стр, хотя преобладает второй вариант. После того как для объекта будет определен оператор <=>, вы также сможете использовать операторы ==, ! =, <, <=, > и >= для сравнения объектов. Если отношения порядка нежелательны, ограничьтесь перегрузкой ==. Аналогично, перегруженная версия cmp используется Bit, gt и других строковых сравнениях лишь при отсутствии их явной перегрузки. Оператор строковой интерполяции обозначается странным именем "" (две кавычки). Он вызывается каждый раз, когда происходит строковое преобразование - например, внутри кавычек или апострофов или при вызове функции print. Прочитайте документацию по директиве overload, прилагаемую к Perl. Перегрузка операторов Perl откроет перед вами некоторые нетривиальные возможности - например, методы строковых и числовых преобразований, автоматическая генерация отсутствующих методов и изменение порядка операндов при необходимости (например, в выражении 5 + $а, где $а является объектом). Пример. Перегруженный класс StrNum Ниже приведен класс StrNum, в котором числовые операторы используются для работы со строками. Да, мы действительно собираемся сделать то, против чего настраивали вас, то есть применить числовые операторы к нечисловым объектам, однако программисты по опыту работы в других языках всегда ожидают, что + и == будут работать со строками. Это всего лишь несложный пример, демонстрирующий перегрузку операторов. Подобное решение почти наверняка не будет использоваться в коммерческой версии программы из-за проблем, связанных с быстродействием. Кроме того, перед вами один из редких случаев использования конструктора, имя которого совпадает с именем класса, - наверняка это порадует программистов со знанием С++ и Python. о! /usr/bin/perl # show strnum - пример перегрузки операторов use StrHum; $х = StrNumCRed"); $у = StrNumCBlack); $z = $х + $у; $г = $z . 3; print "values are $x, $y, $2, and $r\n"; print "$x is ", $x < $y "LT" ; "6E", " $y\n"; values are Red, Black, RedBlack, and 0 Red is GE Black Исходный текст класса приведен в примере 13.1. Пример 13.1. StrNum package StrNum; use Exporter (); @ISA = Exporter; ©EXPORT = qw(StrNum); # Необычно use overload ( <=> => \&spaceship, cmp => \&spaceship, 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 |