Вход на хостинг
IT-новости
20.04.2016 iPhone 2017 года поместят в водонепроницаемый корпус из стекла
Линейка iPhone в новом году серьезно поменяется. В этом уверен аналитический исследователь Мин Чи Ку......
30.07.2015 Ищем уникальный контент для сайта
Ищем уникальный контент для сайта Без уникального контента Ваш сайт обречен на то, что его страницы......
39: print $a->[0]{'next_ref'}{'value'}." ";
40: # здесь вызывается DESTROY
41: }
42: # $ring=7; # это вызовет метод STORE
43:
44: while (1) { tie my $ring, 'MyRing', 10; }
Для упрощения я не стал выделять модуль, описывающий класс, в отдельный файл. Связывать объект будем со скалярной переменной, это тоже, наверное, не лучшее решение: естественнее было бы выбрать массив, а если бы мы захотели сделать нашу разработку более масштабируемой и развиваемой, то логичнее было бы выбрать хэш. Но для связывания таких «сложных» конструкций нам пришлось бы реализовать множество методов, для скаляра же достаточно четырёх, эта компактность и наглядность лучше всего подойдёт для обсуждения в статье.
Итак, в строках 3-27 описан модуль MyRing. Он содержит уже знакомую нам функцию создания и инициализации массива хэшей (create_ring) и методы, необходимые для обеспечения работоспособности связанной переменной.
Метод TIESCALAR (строка 14) вызывается в момент связывания, он получает от оператора tie список дополнительных параметров, в котором у нас будет только одна величина – длина требуемого массива. Получив параметры, метод создаёт наш массив (вызов create_ring($length)), ассоциирует его с классом (вызов bless) и возвращает «новоиспечённый» объект.
Метод FETCH (строка 19) вызывается, когда выполняется чтение значения связанной переменной. Ему передаётся один параметр – сам объект. Наша реализация FETCH не делает ничего, просто возвращает то, что получила без изменений.
Метод STORE (строка 21) отвечает за запись в переменную. Я не придумал, что в него написать, он просто выдаёт грозное сообщение и «убивает» программу.
И наконец, метод DESTROY (строка 23) – это то, что нам нужно. Он вызывается автоматически всегда, когда переменная выходит за область видимости или становится недоступна по другим причинам (например, когда программа завершается). Наш метод DESTROY разрывает кольцевую структуру (строка 25 выглядит знакомо, не правда ли?), позволяя системе сборки мусора довести свою работу до конца.
Со строки 28 начинается основная программа, где мы сейчас и воспользуемся нашим классом MyRing.
В строках 30-42 приведён небольшой фрагмент кода, демонстрирующий работоспособность нашей «кухни».
В строке 32 мы создаём локальную переменную $a, которая будет существовать только в пределах блока, находящегося в строках 31-41. Во вложенном блоке (строки 33-37) мы создаём локальную переменную $ring, которую сразу же связываем с классом MyRing (строка 35). Для проверки корректности структуры $ring записываем строку «test» в её первый узел (строка 36). Для проверки корректности сборки мусора сохраняем копию $ring в $a. Что произойдёт, когда вложенный блок закончится? Оказывается, метод DESTROY не будет вызван! Это и понятно, мы сохранили указатель на нашу структуру (помните? $ring является указателем на массив) в переменной $a, а она всё ещё существует. Переменной $ring не стало, но пропало только имя, данные целы. Мы убеждаемся в этом в строке 39. Здесь же мы убеждаемся в корректности структуры $ring (теперь $a), получив доступ к первому узлу как к узлу, следующему после нулевого. А метод DESTROY будет вызван только тогда, когда исчезнет переменная $a. Таким образом, всё работает правильно.
Обратите внимание и на то, что при выполнении манипуляций с $ring (строка 35) вызывается метод FETCH, отвечающий за чтение переменной, а не STORE, ответственный за запись. Действительно, чтобы проделать операцию, описанную в строке 35, нам пришлось считать значение указателя $ring, а не записать его.