tags:

views:

49

answers:

1

Hi, let's say you've got a Moose class that requires an attribute that does a Role:

package MyMooseClass;
use Moose;

has 'a' => ( does => 'MyRole' );

Now, I'd like to build an instance of MyMooseClass like this:

my $instance = MyMooseClass->new( { a => $a_non_moose_stuff } );

Where $a_non_moose_stuff is an instance of a non-moose class, but that implements the required role methods.

Is there a way to have Moose to check that my $a_non_moose_stuff complies with the role, even though it's not implemented using Moose?

+3  A: 

The easiest thing is to use a duck_type instead of a role to validate your interface. A duck_type is a looser restriction, basically the duck_type is just a list of methods the object is expected to have. For example:

package MyMooseClass;
use Moose;
use Moose::Util::TypeConstraints qw/duck_type/;

has 'a' => (
  isa => duck_type(qw/method1 method1 some_other_method/),
);

See Moose::Util::TypeConstraints and scroll down a bit til you see the entry for duck_type. This constraint was added specifically to deal with this kind of issue.

If you are going to reuse this constraint a lot, you might want to look at creating it in a type library class, which will promote reuse. Check out MooseX::Types.

BTW, although using a Hash Reference in the constructor is supported, and for a long time prior to Moose considered a best practice, most Moose authors I know skip it and just supply a list of constructor parameters. Its a bit less typing and looks cleaner, in my opinion:

my $instance = MyClass->new(param1=>'val1', param2=>'val2');

The main point of the Hash Reference approach was to help solve some ambiguities that really don't happen when you are using Moose to construct your Perl object. Since Moose deals with all that boilerplate and ceremony for you, it is unnecessary in my opinion, although styles do vary. My two cents.

Take it easy,

John

thanks! Exactly what I need. Maybe I can even turn a Role into a ductype :)
jeje
Yep `duck_type` was added as a cheap way to not have to fork and subclass a non-Moose class on CPAN so it could be checked against some API. (EDIT: I need to learn to read.)
perigrin