Вы правы, документация не очень понятна в этой области, тем более что атрибуты не так сложны. Если вы определите атрибут подпрограммы, например так:
sub some_method :Foo { }
Perl при компиляции вашей программы (это важно) ищет магический саб MODIFY_CODE_ATTRIBUTES
в текущем пакете или любом из его родительских классов. Это будет вызвано с именем текущего пакета, ссылкой на вашу подпрограмму и списком атрибутов, определенных для этой подпрограммы. Если этот обработчик не существует, компиляция завершится неудачей.
То, что вы делаете в этом обработчике, полностью зависит от вас. Да это правильно. Никакой скрытой магии. Если вы хотите сообщить об ошибке, возвращение имени атрибутов-нарушителей приведет к сбою компиляции с сообщением «недопустимый атрибут».
Есть еще один обработчик по имени FETCH_CODE_ATTRIBUTES
, который будет вызываться всякий раз, когда кто-то говорит
use attributes;
my @attrs = attributes::get(\&some_method);
Этот обработчик получает имя пакета и ссылку на подпрограмму и должен возвращать список атрибутов подпрограммы (хотя то, что вы действительно делаете, снова зависит от вас).
Вот пример для включения простого «тегирования» методов с произвольными атрибутами, которые вы можете запросить позже:
package MyClass;
use Scalar::Util qw( refaddr );
my %attrs; # package variable to store attribute lists by coderef address
sub MODIFY_CODE_ATTRIBUTES {
my ($package, $subref, @attrs) = @_;
$attrs{ refaddr $subref } = \@attrs;
return;
}
sub FETCH_CODE_ATTRIBUTES {
my ($package, $subref) = @_;
my $attrs = $attrs{ refaddr $subref };
return @$attrs;
}
1;
Теперь в MyClass и всех его подклассах вы можете использовать произвольные атрибуты и запрашивать их, используя attributes::get()
:
package SomeClass;
use base 'MyClass';
use attributes;
# set attributes
sub hello :Foo :Bar { }
# query attributes
print "hello() in SomeClass has attributes: ",
join ', ', attributes::get(SomeClass->can('hello'));
1;
__END__
hello() in SomeClass has attributes: Foo, Bar
Таким образом, атрибуты делают не очень много, что, с другой стороны, делает их очень гибкими: вы можете использовать их как настоящие «атрибуты» (как показано в этом примере), реализовывать что-то вроде декораторов (см. Sinan's ответ ), или для ваших собственных коварных целей.