Vous avez raison, la documentation n'est pas très clair dans ce domaine, surtout depuis que les attributs ne sont pas si compliqué. Si vous définissez une sous-routine d'attribut, comme ceci:
sub some_method :Foo { }
Perl sera lors de la compilation de votre programme (c'est important) regarder pour la magie sous - MODIFY_CODE_ATTRIBUTES
dans le package en cours ou de l'une de ses classes parentes. Ce seront appelés avec le nom du package, une référence à votre routine, et une liste des attributs définis pour cette sous-routine. Si cette fonction n'existe pas, la compilation échoue.
Ce que vous faites dans ce gestionnaire est entièrement à vous. Oui, c'est vrai. Pas de hidden magic que ce soit. Si vous souhaitez signaler une erreur, retourner le nom de la délinquance des attributs sera la cause de la compilation échoue avec un "attribut non valide" message.
Il y a une autre fonction appelée FETCH_CODE_ATTRIBUTES
qui sera appelé à chaque fois que quelqu'un dit
use attributes;
my @attrs = attributes::get(\&some_method);
Ce gestionnaire est transmis le nom du package et de la sous-routine de référence, et est censé renvoyer une liste de la sous-routine attributs (même si ce que vous avez vraiment à faire est de nouveau à vous de voir).
Voici un exemple pour permettre un "marquage" des méthodes arbitraires attributs, que vous pouvez interroger plus tard:
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;
Maintenant, dans MyClass et toutes ses sous-classes, vous pouvez utiliser les attributs arbitraires, et de les interroger à l'aide de 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
En résumé, les attributs ne font pas grand-chose qui les rend très flexible: Vous pouvez les utiliser comme de véritables "attributs" (comme indiqué dans cet exemple), de mettre en œuvre quelque chose comme les décorateurs (voir Sinan réponse), ou pour votre propre sournois fins.