Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Moose: How to check if a class implements a role?

by Monk::Thomas (Beadle)
on Jul 12, 2013 at 14:57 UTC ( #1043993=perlquestion: print w/ replies, xml ) Need Help??
Monk::Thomas has asked for the wisdom of the Perl Monks concerning the following question:

Hello everyone

Is it possible to do something like?

if ( $class->has_role('xyz') ) { [...] }
http://search.cpan.org/dist/Moose/lib/Moose/Manual/Roles.pod goes into detail on how to apply roles, but not if it's possible to query them

Verbose explanation:

I have a couple of roles that the objects can consume. Let's say they provide some functionality for interfacing with the filesystem and the roles are 'Readable' and 'Writeable'. I think it would be very nifty to simply ask an object if it implements/consumes the role 'Writeable' and if it doesn't then I can issue some kind of notification.

The naive implementation would be to check for $obj->write() or similiar, but there may be more then one methods to 'change something' and I don't really want to check every one of them for presence. (Sooner or later one of these methods ~will~ be forgotten.)

Comment on Moose: How to check if a class implements a role?
Download Code
Re: Moose: How to check if a class implements a role? (does)
by Anonymous Monk on Jul 12, 2013 at 14:59 UTC
      Thanks. That is exactly what I was looking for. It even works when applying a role during runtime. (This comes quite handy for implementing a dummy backend class which can fake different feature-set. Think something along the line of DBI, where you want to test the DBI class, but not the actual backend like DBD::mysql)

      (Moose)

      sub BUILD { my $self = shift; my $mode = $self->get_mode(); # normally roles are not used/required, but since we manipulate this # class' roles at runtime we need to require the role if ($mode =~ /R/xmsi) { require TLA::Datastore::_readable; TLA::Datastore::_readable->meta->apply($self); } if ($mode =~ /W/xmsi) { require TLA::Datastore::_writeable; TLA::Datastore::_writeable->meta->apply($self); } if ($mode =~ /X/xmsi) { require TLA::Datastore::_execute; TLA::Datastore::_execute->meta->apply($self); } return; }
      And later I can test for a specific role:
      my $ds = TLA::Datastore::Dummy->new('mode' => 'R'); if ( $ds->DOES('TLA::Datastore::_readable') ) { # do stuff };
Re: Moose: How to check if a class implements a role?
by tobyink (Abbot) on Jul 13, 2013 at 07:27 UTC

    There's $obj->does("MyRole") supported by Role::Tiny, Moo::Role, Mouse::Role, Moose::Role and Stevan Little's current prototype for a core Perl 5 mop, but I'd personally recommend using $obj->DOES("MyRole") (which is also supported by all of the above frameworks) because that's defined in UNIVERSAL, the base class for all Perl classes, and thus you're pretty much guaranteed to not get a Can't locate object method "does" via package "Foobar" error message (unless the class has gone seriously out of its way to prevent you calling DOES).

    package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1043993]
Approved by moritz
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (7)
As of 2014-09-21 14:41 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (172 votes), past polls