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

Hi Monks, Trying to use override with my Moose::Role doesn't work if I am overriding a parent role's implementation.

package top; use Moose::Role; requires 'token'; sub foo { print "foo\n"; } sub useful_method{ print "I'm useful\n" } package bottom; use Moose::Role; with 'top'; override 'foo' => sub { print "bar\n"; }; package something; use Moose; with "bottom"; sub token { print "implement me in the concrete class"; } package main; my $something = new something; $something->foo;

Gives "Cannot add an override of method 'foo' because there is a local version of 'foo'". Just putting a normal sub instead of override doesn't work etither. I get: "Due to a method name conflict in roles 'bottom' and 'top', the method 'foo' must be implemented or excluded by 'something'". Basically the problem is: I want to use top's useful_method and bottom's foo and I don't want to implement "token" until the concrete class. Why can't I use Roles in this way?

Thanks!

Replies are listed 'Best First'.
Re: Moose Roles and Override
by lune (Pilgrim) on Feb 07, 2012 at 12:02 UTC
    Explained in Method Conflicts and in the following section "Method Exclusion and aliasing".
    package top; use Moose::Role; requires 'token'; sub foo { print "foo\n"; } package bottom; use Moose::Role; with 'top' => { -alias =>{ foo => '_foo', }, -excludes => [ 'foo' ], }; sub foo { print "bar\n"; } package something; use Moose; with "bottom"; sub token { print "I don't want to implement token untill the concerete class +but I want to use bottom's version of foo\n"; } package main; my $something = new something; $something->foo;

      Thanks for your quick helpful response. It works and solved my problem perfectly. I think It would be cool if override/super could be used.

Re: Moose Roles and Override
by Oberon (Monk) on Sep 17, 2019 at 01:58 UTC

    (I know I'm replying to a really old thread, but this is still one of the top Google search results for things like "moose role override", so I think it's worth adding a bit to the discussion. Hopefully this is helpful for people who stumble across this in the future.)

    The reason this feature doesn't (and can't, really) work as edwinorc would hope is that there is no such thing as a "parent role." At composition time, all roles are equal. Regardless of how they got to the composing class, all their guts are just jammed into the class at once (or at least that's how I like to think of it). So this works:

    package Role { use Moose::Role; before foo => sub {}; } package Class { use Moose; sub foo {} with 'Role'; }

    because this works:

    package Class { use Moose; sub foo {} before foo => sub {}; }

    On the other hand, this doesn't work:

    package Role { use Moose::Role; override foo => sub {}; } package Class { use Moose; sub foo {} with 'Role'; }

    because this doesn't work:

    package Class { use Moose; sub foo {} override foo => sub {}; }

    And likewise this:

    package Top { use Moose::Role; sub foo {} } package Bottom { use Moose::Role; override foo => sub {}; with 'Top'; } package Class { use Moose; with 'Bottom'; }

    is just equivalent to this:

    package Class { use Moose; sub foo {}; override foo => sub {}; }

    so, again, it can't work. The fact that Top got composed via Bottom doesn't really matter.