Reputation: 524
I'm a bit new to Perl. I'm trying to define/use a class in the following manner:
package A::B::C;
use strict;
use warnings;
use Moose;
use aliased 'A::B::D';
has 'attribute' => (isa => 'ArrayRef[D]', is => 'ro', required => 1);
While creating an object:
use aliased 'A::B::C';
use aliased 'A::B::D';
my $aref = [D->new()];
C->new($aref);
However this fails as Moose complains:
Attribute (attribute) does not pass the type constraint because: Validation failed for 'ArrayRef[D]' with value ARRAY(0x7f2b658b51c0)
But, if I switch to not using aliases, it works(as it of course should):
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);
My question is why does the use aliased bit not work with Moose?
Thanks
Upvotes: 1
Views: 53
Reputation: 4635
Moose doesn't know about use aliased
. The pragma use aliased
is a hack on top of Perl; all it does is create a subroutine with a short name that returns the class name. So
use aliased 'A::B::D';
is equivalent to
use A::B::D;
sub D() { 'A::B::D' }
(see aliased.pm#L45)
Then, when you say something like D->new()
, Perl notices that there is a subroutine (constant) named D
and interprets D
as a subroutine call, then does the method call on the result. (Rather than interpreting D
as a string constant like it normally would). Even to Perl, D
is not really a package name; just something that acts like a package name!
Furthermore, Moose has its own system for parsing type declarations (which is why you can give them as a string like you did) and its own global notion of type declarations. None of that knows about aliased
, so Moose is using its default behavior of treating un-recognized types as (global) package names.
If you understand how aliased
works, you could take advantage of it by doing
has 'attribute' => (isa => 'ArrayRef['.D.']', is => 'ro', required => 1);
but it's probably better to remember that
Type names are global throughout the current Perl interpreter
and either use fully-qualified package names as types everywhere, or use Type::Tiny and write
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);
(note the lack of quotes around D
, possible only because of the use aliased
!).
(Type::Tiny
will probably be faster than Moose types, so you might want to consider it anyway).
Upvotes: 1