Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses

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

by Monk::Thomas (Friar)
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') ) { [...] } 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.)

Replies are listed 'Best First'.
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)


      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?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1043993]
Approved by moritz
[Discipulus]: Eily i'm testing a failure: i ok if i get bad results.. perhaps there is another way to do it...
[Discipulus]: in other words: i have a contructor that carps on missing arguments and I want to test that it fails correctly, without carping out in the test output

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (7)
As of 2018-01-22 11:31 GMT
Find Nodes?
    Voting Booth?
    How did you see in the new year?

    Results (233 votes). Check out past polls.