2017-07-11 4 views
1

Je suis un peu nouveau pour Perl. Je suis en train de définir/utiliser une classe de la manière suivante:utilisant aliased avec Moose ne semble pas fonctionner lors de la déclaration des classes

package A::B::C; 
use strict; 
use warnings; 
use Moose; 
use aliased 'A::B::D'; 
has 'attribute' => (isa => 'ArrayRef[D]', is => 'ro', required => 1); 

Lors de la création d'un objet:

use aliased 'A::B::C'; 
use aliased 'A::B::D'; 
my $aref = [D->new()]; 
C->new($aref); 

Cependant cela ne fonctionne pas comme Moose se plaint:

Attribute (attribute) does not pass the type constraint because: Validation failed for 'ArrayRef[D]' with value ARRAY(0x7f2b658b51c0) 

Mais, si je passe à ne pas utiliser d'alias, cela fonctionne (comme il se doit bien sûr):

package A::B::C; 
use strict; 
use warnings; 
use Moose; 
use A::B::D; 
has 'attribute' => (isa => 'ArrayRef[A::B::D]', is => 'ro', required => 1); 

Ma question est pourquoi le bit alias d'utilisation ne fonctionne pas avec Moose?

Merci

Répondre

1

Moose ne connaît pas use aliased. Le pragma use aliased est un hack au-dessus de Perl; tout ce qu'il fait est de créer un sous-programme avec un nom court qui retourne le nom de la classe. Alors

use aliased 'A::B::D'; 

est équivalent à

use A::B::D; 

sub D() { 'A::B::D' } 

(voir aliased.pm#L45)

Alors, quand vous dites quelque chose comme D->new(), Perl remarque qu'il ya un sous-programme (constante) du nom D et interprète D En tant qu'appel de sous-programme, la méthode appelle le résultat. (Plutôt que d'interpréter D comme une constante de chaîne comme elle le ferait normalement). Même pour Perl, D n'est pas vraiment un nom de paquet; juste quelque chose qui agit comme un nom de paquet! En outre, Moose a son propre système pour analyser les déclarations de type (ce qui explique pourquoi vous pouvez les donner comme une chaîne comme vous) et sa propre notion globale de déclarations de types. Rien de cela ne connaît environ aliased, donc Moose utilise son comportement par défaut de traitement des types non reconnus comme noms de paquets (globaux).

Si vous comprenez comment aliased fonctionne, vous pourriez en profiter en faisant

has 'attribute' => (isa => 'ArrayRef['.D.']', is => 'ro', required => 1); 

mais il est probablement mieux de se rappeler que

Type names are global throughout the current Perl interpreter

et soit utiliser pleinement -qualifié les noms de paquets comme types partout, ou utilisez Type::Tiny et écrivez

package A::B::C; 

use Moose; 

use aliased 'A::B::D'; 

use Types::Standard qw/ ArrayRef /; 
use Type::Utils qw(class_type); 

has 'attribute' => (isa => ArrayRef[class_type D], is => 'ro', required => 1); 

(notez l'absence de guillemets autour D possible seulement à cause de la use aliased!).

(Type::Tiny sera probablement plus rapide que les types Moose, donc vous pourriez vouloir le considérer de toute façon).

+0

est-ce la façon standard/recommandée d'utiliser des noms abrégés pour les importations? Ce que je veux m'assurer, c'est que l'approche que je finis par utiliser ne possède pas de telles pièges et fonctionne seulement lorsqu'elle est utilisée comme remplacement pour spécifier le chemin entier. – user2103008