; builder: alternative to default—
name of a method that will generate
the default.
; lazy: if true, the attribute is not
initialized until it’s used.
; required: if true, attribute value must
be provided to constructor or have
default/builder.
Attributes Containing Objects
So far, I’ve talked only about attributes
containing simple scalars. Attributes
can contain other types of values as
well, including references and other
objects. For example, you could add a
DateTime attribute to your MyApp::Rifle
class to keep track of the last time
“fire” was called:
package MyApp::Rifle;
use Moose;
use DateTime;
The builder option lets you specify
a method to use to populate the
attribute’s default value. A builder is a
normal method defined within the class,
and its return value is used to set the
attribute’s initial value. If the builder
needs to access other attributes within
the object, the attribute must be lazy
(to prevent it from potentially being
populated before the other attributes
it depends on).
Because this is such a common sce-
nario, for convenience, Moose provides
the “lazy_build” attribute option that
automatically sets the lazy option and
sets the builder to _build_name (such as _build_first_name for an attribute
named first_name). For example: }
has 'rounds' => ( is => 'rw', isa => 'Int', default => 0 );
has 'fired_dt' => ( is => 'rw', isa => 'DateTime' );
sub fire {
my $self = shift;
die "out of ammo!" unless ($self->rounds > 0);
my $dt = DateTime->now( time_zone => 'local' );
$self->fired_dt($dt);
print "bang!\n";
print "fired at " . $self->fired_dt->datetime . "\n";
$self->rounds( $self->rounds - 1 );
has 'first_name' => ( is => 'ro', lazy_build => 1 );
sub _build_first_name {
my $self = shift;
return $self->some_lookup('some data');
1;
}
This is fairly straightforward. I’m cre-
ating a new DateTime object and storing
it in my fired_dt attribute. Then, I can
WWW.LINUXJOURNAL.COM SEPTEMBER 2011 | 129