Consider the following code sample:
use Moops;
role RoleA
using Moose {
requires 'm1';
method m2() {
$self->m1." World!\n";
}
}
role RoleB
using Moose {
has 'm1' => ( accessor => 'm1', is => 'ro', isa => 'Str', default => 'Hello');
}
class ClassA
with RoleB
with RoleA
using Moose {
method m3() {
$self->m2();
}
}
print ClassA->new()->m3();
"Compilation" fails, because the attribute accessor does not seem to satisfy the roles request for m1
:
$ perl roletest.pl
'RoleB|RoleA' requires the method 'm1' to be implemented by 'ClassA' at /usr/lib/perl5/site_perl/Moose/Meta/Role/Application/ToClass.pm line 134.
Moose::Meta::Role::Application::ToClass::check_required_methods('Moose::Meta::Role::Application::ToClass=HASH(0x28b9d00)', 'Moose::Meta::Role::Composite=HASH(0x28c6270)', 'Moose::Meta::Class=HASH(0x28ee7c0)') called at /usr/lib/perl5/site_perl/Moose/Meta/Role/Application.pm line 55
Moose::Meta::Role::Application::apply('Moose::Meta::Role::Application::ToClass=HASH(0x28b9d00)', 'Moose::Meta::Role::Composite=HASH(0x28c6270)', 'Moose::Meta::Class=HASH(0x28ee7c0)') called at /usr/lib/perl5/site_perl/Moose/Meta/Role/Application/ToClass.pm line 36
Moose::Meta::Role::Application::ToClass::apply('Moose::Meta::Role::Application::ToClass=HASH(0x28b9d00)', 'Moose::Meta::Role::Composite=HASH(0x28c6270)', 'Moose::Meta::Class=HASH(0x28ee7c0)', 'HASH(0x28e3410)') called at /usr/lib/perl5/site_perl/Moose/Meta/Role.pm line 470
Moose::Meta::Role::apply('Moose::Meta::Role::Composite=HASH(0x28c6270)', 'Moose::Meta::Class=HASH(0x28ee7c0)') called at /usr/lib/perl5/site_perl/Moose/Util.pm line 163
Moose::Util::_apply_all_roles('Moose::Meta::Class=HASH(0x28ee7c0)', undef, 'RoleB', 'RoleA') called at /usr/lib/perl5/site_perl/Moose/Util.pm line 99
Moose::Util::apply_all_roles('Moose::Meta::Class=HASH(0x28ee7c0)', 'RoleB', 'RoleA') called at /usr/lib/perl5/site_perl/Moose.pm line 66
Moose::with('Moose::Meta::Class=HASH(0x28ee7c0)', 'RoleB', 'RoleA') called at /usr/lib/perl5/site_perl/Moose/Exporter.pm line 409
Moose::with('RoleB', 'RoleA') called at roletest.pl line 16
main::BEGIN() called at roletest.pl line 23
eval {...} called at roletest.pl line 23
BEGIN failed--compilation aborted at roletest.pl line 23.
Using plain Moose
and Moose::Role
this works (as is documented here). Also, not using the Moose
backend works to.
I already tried switching the order of the with
statements to no avail. Replacing the attribute with a method declaration solves the problem, but I need a way to specify attribute requirements.
Is there a way to get this working?
Are you sure it works with plain Moose? Because I've tried this and it fails with a very similar error message:
There are a number of issues in Moose (and corresponding TODO test cases in the test suite) revolving around attributes in roles not satisfying
requires
in other roles. For example, bug RT#77406 is similar (though not identical).UPDATE by manually composing the roles one-at-a-time, in a particular order, you can make it work: