BUILD is never called in composed roles. The primary reason is that role are *not* order
sensitive. Roles are composed in such a way that the order of composition does not matter
(for information on the deeper theory of this read the original traits papers here (http://
www.iam.unibe.ch/~scg/Research/Traits/)). Because roles are essentially un-ordered, it
would be impossible to determine the order in which to execute the BUILD methods.
As for alternate solutions, there are a couple.
1) Using a combination of lazy and default in your attributes to defer initialization (see the
Binary Tree example of lazy/default usage here (
http://search.cpan.org/~stevan/
Moose-0.21/lib/Moose/Cookbook/Recipe3.pod))
2) Use attibutes triggers, which fire after an attribute it set to faciliate initialization. These are
described in the Moose.pm docs and examples can be found in the test suite.
In general, roles should not I<require> intialization, they should either provide sane defaults
or should be documented as needing specific initialization. One such way to "document" this
is to have a seperate attribute initializer which is required for the role. Here is an example of
how to do this:
package My::Role;
use Moose::Role;
has 'height' => (
is => 'rw',
isa => 'Int',
lazy => 1,
default => sub {
my $self = shift;
$self->init_height;
}
);
requires 'init_height';
In this example, the role will not compose successfully unless the class provides a
C<init_height> method.
If none of those solutions work, then it is possible that a role is not the best tool for the job,
and you really should be using classes. Or, at the very least, you should reduce the amount
of functionality in your role so that it does not require initialization.
Hope this helps,
- Stevan
FYI - I have added this into the Moose::FAQ/WTF pod files as well, it should show up in the
next release. In the future, quesitons like this are better sent to the mailing list or asked on
the #moose channel, since this is not really a bug.