perlquestion
Boldra
<p>
I want a role to consume another role, and provide an attribute that the consumed role requires, but Moose won't see the attribute provided by the first role.
<p>
An example:
<C>
package Role::Logger;
use Moose::Role;
requires qw<smeg>;
package Role::App;
use Moose::Role;
has smeg => ( is => 'rw' );
with 'Role::Logger';
package App::FixIt;
use Moose;
with "Role::App";
sub run {
print "smeg=" . shift->smeg;
}
package main;
use Moose;
App::FixIt->new( { smeg => 1 } )->run;
</C>
<P>This code returns the error <TT>'Role::App' requires the method 'smeg' to be implemented by 'App::FixIt'</TT>. But <TT>Role::App</TT> doesn't have any requirements, it's <TT>Role::Logger</TT> which requires smeg, and smeg is provided by <TT>Role::App</TT>.
<p>
The <A HREF="http://search.cpan.org/~doy/Moose-2.0200/lib/Moose/Manual/Roles.pod#Required_Attributes">Moose documentation to required attributes</A> warns that a requirement met by an <i>attribute</i> in a consuming <i>class</i> must be met <i>before</i> the role is consumed, so:
<C>
package Role::App;
use Moose::Role;
requires 'gazpacho';
package App::FixIt;
use Moose;
with Role::App;
has gazpacho => ( is => 'rw' );
</C>
breaks because the requirement is met <i>after</i> the role is consumed. Here, swapping the order of <tt>with</tt> and <tt>has</tt> solves the problem. OTOH, requirement met by a subroutine would also be ok, because the subroutine is defined before with imposes the <tt>required</tt> constraints at runtime.
<p>
In summary:
If a role requires a method and the requirement is met by:
<table border=1>
<tr><td>a <b>sub</b> in a consuming <b>class</b></td><td>No problem</td></tr>
<tr><td>a <b>sub</b> in a consuming <b>role</b></td><td>No problem</td></tr>
<tr><td>an <b>attribute</b> in a consuming <b>class</b></td><td>be careful of the has/with order</td></tr>
<tr><td>an <b>attribute</b> in a consuming <b>role</b></td><td><em>can't be done?</em></td></tr>
</table>
<p>
Thanks for your thoughts!
</p>