Search code examples
perlmoose

Why a Moose Role method overrides parents definition?


The method a defined in both A and in A::B.

C is derived from A and uses A::B.

Question 1: Why A::B->a override A->a?

$ perl x.pl 
b

Question 2: Why A::B->a wouldn't override C->a, if we add sub a {'c'} into C?

A.pm: base class

package A;
use Moose;
sub a {
    return 'a';
}
no Moose;
1;

A/B.pm: a role

package A::B;
use Moose::Role;
sub a {
    return 'b';
}
1;

C.pm: a class derived from A with the role A::B

package C;
use Moose;
extends "A";
with "A::B";
no Moose;
1;

bin.pl

use v5.10;
use strict;
use warnings;
use C;
my $c = C->new();
say $c->a;

Solution

  • package C;
    use Moose;
    extends 'A';
    

    makes package C a subclass of A. Behind the scenes, it adds A to @C::ISA. When an object of type C calls a method and the method name is not found in namespace C, perl will inspect the namespaces in @C::ISA to look for a way to resolve the method name.

    package C;
    use Moose;
    with 'A::B';
    

    does something different. It does not make C a subclass of A::B. It copies entries from the A::B namespace into the C namespace.

    So when you call $c->a, Perl finds a subroutine &C::a because it was copied from &A::B::a, and that's what it uses. It does not need to walk through @C::ISA to search for another subroutine named a.


    If you also define a sub a { ... } in package C, then use Moose ... with 'A::B' will not overwrite it.