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

Moo role subclassing

by Anonymous Monk
on Feb 24, 2016 at 16:27 UTC ( #1156033=perlquestion: print w/replies, xml ) Need Help??

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

G'day wise monastery dwellers, I am using Moo and would like to be able to subclass some of my Moo::Roles, but unfortunately this does not seem to be possible (unless I'm doing something wrong). I'd like to be able to override the attributes in subclassed roles in addition to adding extra functions, e.g.
package BasicRole; use Moo::Role; has 'attrib' => ( is => 'ro' ); sub do_something { ... } 1; package NotSoBasicRole; use Moo; extends 'BasicRole'; has '+attrib' => ( default => sub { return 1; } ); 1; package SpecialRole; use Moo; extends 'NotSoBasicRole; has '+attrib' => ( default => sub { return 2; } ); sub do_something_else { ... } 1;
However, trying to extend a Moo::Role gives the error "Can't extend role" (see also https://github.com/moose/Moo/blob/master/t/extends-role.t). Is there a nice way to handle this situation?

Replies are listed 'Best First'.
Re: Moo role subclassing
by Arunbear (Prior) on Feb 24, 2016 at 18:38 UTC
    Roles are not designed to be subclassed (because a role is not a class), but you can compose a role out of other roles, so you could do something like this:
    package BasicRole; use Moo::Role; has 'attrib' => ( is => 'ro' ); sub do_something { ... } 1; package NotSoBasicRole; use Moo::Role; with 'BasicRole'; has '+attrib' => ( is => 'ro', default => sub { return 1; } ); 1; package SpecialRole; use Moo::Role; with 'NotSoBasicRole'; has '+attrib' => ( is => 'ro', default => sub { return 2; } ); sub do_something_else { ... } 1; package App; use Moo; with 'BasicRole'; 1; package AnotherApp; use Moo; with 'SpecialRole'; 1; package main; use v5.10; no warnings; my $app = App->new(); say $app->attrib; my $another_app = AnotherApp->new(); say $another_app->attrib;
      Perfect, thank you! I had completely overlooked composition.
Re: Moo role subclassing
by arkturuz (Curate) on Feb 24, 2016 at 17:05 UTC
    You cannot subclass a role, you must use it. From the documentation, this is how you use a role:
    # bar gets imported, but not foo with('My::Role');

      Thank you for the response; I omitted the code where the roles are used, but it would look something like this:

      package App; use Moo; with 'BasicRole'; ... package AnotherApp; use Moo; with 'SpecialRole'; ...

      Since Moo does not allow roles to be extended, I am wondering if there is some magical, elegant way to implement what would essentially be subclasses of roles. I have some ugly, inelegant ideas for implementation, but was hoping that there might be something I'd missed.

        The whole point about roles is that they don't belong to an inheritance hierarchy and avoid thus the trouble sometimes associated with complex inheritance trees. Roles are composed into classes (and perhaps even, I do not know in the case of Moo, into object instances), but they don't inherit not can be subclassed.

        If you need inheritance and subclassing, use a class instead.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1156033]
Approved by davido
Front-paged by Tanktalus
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (3)
As of 2021-07-31 10:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?