49 votes

Comment fonctionnent les attributs de la méthode Perl?

Un peu connu intégré dans Perl fonction est d'attributs. Toutefois, le fonctionnaire de la documentation est en train de faire un assez mauvais travail de l'introduction de débutants à la notion. Dans le même temps, les cadres comme Catalyseur utiliser des attributs largement ce qui semble rendre les choses beaucoup plus facile là. Depuis l'utilisation de quelque chose sans en connaître les implications suce un peu, j'aimerais en connaître les détails. La syntaxe du sage, ils ressemblent à des décorateurs Python, mais la documentation implique quelque chose de plus simple.

Pourriez-vous expliquer (avec des exemples du monde réel si possible) quels sont les attributs sont bon et ce qui se passe derrière les portes?

40voto

trendels Points 2929

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.

11voto

Sinan Ünür Points 76179

5voto

Axeman Points 24103

Les attributs sont l'une des choses que si vous ne savez pas comment les utiliser, vous ne devriez pas vous ennuyer avec eux. Une fois, j'ai fait une database_method attribut pour indiquer au système que d'un ensemble d'enregistrements seraient demandés avant d'entrer dans cette méthode et la méthode savait principales entrées viendrait de la procédure stockée elle correspondait.

J'ai été en utilisant les attributs d'envelopper le réel, les actions spécifiées avec ces données. Ainsi, l'un des vraiment apparemment utile, des idées consiste à envelopper les méthodes avec indirection, mais c'était plus difficile de faire de l'appelant de travail, sans remplaçant. En fin de compte, il était beaucoup trop visible comme un "expert seule" fonction et aurait besoin de soutien, de tracer à travers les arcanes entrailles--quelque chose que vous voulez éviter, si vous écrivez Perl perl-aussi boutique.


Les gens peuvent vouloir voter me calmer, mais je prends de l'article cité par Sinan:

Mises en garde

Bien que ce est une technique puissante, il n'est pas parfait. Le code n'affiche pas correctement les envelopper anonyme sous-routines, et il ne sera pas nécessairement propager l'appel le contexte de la enveloppé fonctions. En outre, en utilisant cette technique permettra d'accroître considérablement le nombre de sous-routine, les dépêches que votre programme doit exécuter au cours de l'exécution. En fonction de votre programme de la complexité, ce qui peut augmenter considérablement la taille de votre pile d'appel. Si aveuglant la vitesse est l'un des principaux objectifs de la conception, cette stratégie est peut-être pas pour vous.

Ce sont d'importants inconvénients, sauf si vous êtes prêt à remplacer caller. Je ne me préoccupe pas "une vitesse surhumaine" tout à fait autant, et je suis à mi-prêt à essayer ma main à l'impérieuse caller de contourner un sous-programme qui s'inscrit lui-même comme "DO_NOT_REPORT" -- mais j'ai un peu de codage de la témérité qui n'a pas encore été battu hors de moi, trop.

Même l'article admet comment mal documenté cette caractéristique est, et contient cette mise en garde. Dites-moi quand autre chose, elle a été une bonne idée d'utiliser un snazzy, fonctionnalité obscure? Que, assez souvent, les gens finissent par mettre dans l' UNIVERSAL d'espace de noms pour éviter la question de l'héritage.

(Mais si vous pensez que c'est une mauvaise réponse, juste un autre downvote va me donner une pression des pairs badge :D)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X