Building A Better Moose Trap
Seem there are a number of little oddities in Moose that take a little time to absorb, but once you figure them out you wonder what you ever did before. In my last post I was doing a little refactoring and I decide to look at a few more things.
You may recall early on in my 'Character' class I had the following attribute
has 'class' =>(
is =>'ro',
isa =>'HashRef|Str',
);
Meaning that I could enter a hashref or a string for 'class'. Well there is a much better way to do this sort of thing and that is with 'coercion'.
This is accomplished with a Roles of Type Constraints for the items you want to coerce.
So our role will look like this
package RPG::ADD::Types;
use Moose::Role;
use Moose::Util::TypeConstraints;
subtype 'ClassIn',
as 'HashRef';
coerce 'ClassIn',
from 'Str',
via { { $_=>0} };
So I have created 'ClassIn' which is a subtupe of a the standard 'HashRef' and then I add in a coerce directive that tells Moose to take any 'Str' that is passed in and turn it into a hash as well.
The next part is to import this role into my 'Character' class like this
use Moose;
with 'RPG::ADD::Types';
and then change my 'class' attribute like this
has 'class' =>(
is =>'ro',
isa =>'ClassIn',
coerce => 1
);
then then both
my $str = RPG::ADD::Character->new({class=>{Fighter=>1,Thief=>8},...
and
my $str = RPG::ADD::Character->new({class=>Fighter,...
just work and I can change my BUILD so I no longer have to check if I am passing in a 'HashRef' so now it looks allot cleaner like this
$attr->{self} = $self;
$attr->{attr} = $attr;
apply_all_roles($self,("RPG::ADD::Class::Multi",=>$attr));
Well worth the little effort I put into it. I can see this coming in very handy when I eventually have to do arrays of equipped items such as weapons or even spells that a character might have memorized.
Sort of reminds me of 'constructors' in Java though this I think is a much better way to go about it.
Leave a comment