2010-02-15 3 views
3

J'ai un rôle et plusieurs classes qui mélangent le rôle. La classe Rôle charge toutes les classes d'implémentation afin que tout ce qui importe Blah puisse les utiliser sans avoir à saisir beaucoup de lignes 'use'.Pourquoi l'application de rôle Moose avec les modificateurs de méthode ne fonctionne-t-elle pas dans mon code?

package Blah; 
use Moose::Role; 

use Blah::A; 
use Blah::B; 
(etc...) 

requires '...'; 
requires 'foo'; 
around 'foo' => sub { ... } 

Une sous-classe Blah typique:

package Blah::A; 
use Moose; 
with 'Blah'; 

sub foo { ... } 

__PACKAGE__->meta->make_immutable; 

Étant donné que chaque méthode sous-classe de foo 'commence par les mêmes bits de code, le rôle met en œuvre également par l'intermédiaire d'un modificateur de la méthode.

Problème: Moose n'applique le modificateur de méthode à aucune des classes Blah :: *. Cela se produit même si je supprime l'appel make_immutable pour les classes. Je pensais que l'application de rôle était entièrement réalisée au moment de l'exécution, et donc même si les classes Blah :: * sont chargées avant Blah, le modificateur devrait toujours être appliqué? Je cherche une solution, ou une autre façon de faire les choses. À l'heure actuelle, Blah est essentiellement une classe de base abstraite à l'exception du modificateur de méthode, c'est pourquoi j'ai utilisé des rôles pour commencer - mais peut-être qu'une hiérarchie de classes serait meilleure? Merci d'avance.

Répondre

4

Votre commande d'appel est un peu étrange - pourquoi êtes-vous use ing Blah :: A à partir du rôle qui est ensuite appliqué à Blah :: A?

Je suggère d'extraire ces lignes use et de les déplacer là où elles sont réellement nécessaires (dans l'appelant (s)). Faites fonctionner le code en premier, et après cela, si vous avez beaucoup de lignes use encombrantes partout, vous pouvez les déplacer dans un fichier Includes. Mais non, en réponse à votre hypothèse, l'application de rôle est et non effectuée à l'exécution, mais à tout moment, la ligne with est rencontrée. Si vous use un module à la compilation, alors ce fichier est compilé immédiatement, et la ligne with est exécutée (ce qui oblige alors à compiler le rôle, puis il est exécuté). Vous pouvez bien sûr également appliquer un rôle à l'exécution (voir par exemple apply_all_roles dans Moose::Util), mais ce n'est pas ce qui se passe ici.

+0

Accepté, merci.Les lignes d'utilisation sont ennuyantes, mais je suppose que je vais écrire un module d'usine pour elles au lieu de surcharger le module de rôle :) – rjh

+0

@rjh: oui, vous chargez juste ces modules cible trop tôt, avant que le rôle ait eu une chance finir de se construire et de s'y appliquer. – Ether

-1

Je pense que vous vous méprenez simplement sur la différence entre l'inclusion de fichier et la composition des rôles.

Sous le capot, use déclarations appellent simplement require et la déclaration de paquet déduit import() et envelopper tout cela dans un bloc BEGIN {}.

Il n'installe pas les fonctions en tant que méthodes de méta-classe avec Class :: MOP (CMOP). Je ne suis pas sûr de savoir quelle est la différence entre une méthode déclarée et une méthode importée, ou comment CMOP indique la différence, mais cela ne fonctionne que grâce à l'appel à add_method. Je demanderais plus d'informations à irc.perl.org/#moose, mais je suis banni. J'espère que cet exemple vous dira ce dont vous avez besoin, ou vous donnera plus d'informations pour formuler une meilleure question.

package Class; 
use Moose; 
use Carp qw(carp); 

### You have to add the method onto the class. 
Class->meta->add_method('carp' => \&carp); 

around 'carp' => sub { warn "this won't trigger" }; 

package main; 

my $c = Class->new; 
$c->carp('foo'); 

Si possible je réécris ces paquets votre use ing dans des rôles Moose amis, alors que le rôle actuel appelle les nouveaux rôles en utilisant l'instruction with. Les rôles géreront les modificateurs de méthode autour d'autres méthodes fournies par les rôles.

+1

Evan Je pense que vous avez complètement raté la question ici. Il * utilise * un rôle (Blah est un Moose :: Role). Ses problèmes sont liés aux instructions d'utilisation circulaires (utiliser une classe dont le rôle que vous définissez actuellement est mauvais M'kay?) Et au timing (la composition telle qu'indiquée par ether se produit lorsque le 'with 'est vu, et peut causer des problèmes). Je ne vois pas comment votre exemple ici a quelque chose à voir avec la question puisqu'il n'utilise ni les importations, ni montré un exemple d'une méthode entièrement écrasante avec un modificateur 'around' comme vous l'avez fait ici. Rjh est libre d'entrer dans #moose pour plus d'informations. – perigrin

+0

En allant jusqu'à chauve-souris, je vais supposer que le problème est * spécifique * aux cas 'use' parce que ce code fonctionnera sans (supprimer l'utilisation et nécessite) instancier 'Blah :: A', et je crois que le 'autour' fonctionnera. Peut-être que j'ai essayé d'en déduire beaucoup. –

Questions connexes