has 'name' => ( is => 'rw', isa => 'Str', required => 1 );
has 'address' => ( is => 'rw', isa => 'Address' );
- has 'employees' => ( is => 'rw', isa => 'ArrayRef[Employee]' );
+ has 'employees' => (
+ is => 'rw',
+ isa => 'ArrayRef[Employee]',
+ default => sub { [] },
+ );
sub BUILD {
my ( $self, $params ) = @_;
- foreach my $employee ( @{ $self->employees || [] } ) {
+ foreach my $employee ( @{ $self->employees } ) {
$employee->employer($self);
}
}
after 'employees' => sub {
my ( $self, $employees ) = @_;
- foreach my $employee ( @{ $employees || [] } ) {
+ return unless $employees;
+ foreach my $employee ( @$employees ) {
$employee->employer($self);
}
};
The next attribute, C<employees>, uses a I<parameterized> type
constraint:
- has 'employees' => ( is => 'rw', isa => 'ArrayRef[Employee]' );
+ has 'employees' => (
+ is => 'rw',
+ isa => 'ArrayRef[Employee]'
+ default => sub { [] },
+ );
This constraint says that C<employees> must be an array reference
where each element of the array is an C<Employee> object. It's worth
noting that an I<empty> array reference also satisfies this
-constraint.
+constraint, such as the value given as the default here.
Parameterizable type constraints (or "container types"), such as
C<ArrayRef[`a]>, can be made more specific with a type parameter. In
To do that, we need to hook into object construction. Moose lets us do
this by writing a C<BUILD> method in our class. When your class
-defines a C<BUILD> method, it will be called immediately after
-object construction, but before the object is returned to the caller
-(3). Note that all C<BUILD> methods in your class hierarchy will be
-called automatically; there is no need to (and you should not) call
-the superclass C<BUILD> method.
+defines a C<BUILD> method, it will be called by the constructor
+immediately after object construction, but before the object is returned
+to the caller. Note that all C<BUILD> methods in your class hierarchy
+will be called automatically; there is no need to (and you should not)
+call the superclass C<BUILD> method.
The C<Company> class uses the C<BUILD> method to ensure that each
employee of a company has the proper C<Company> object in its
sub BUILD {
my ( $self, $params ) = @_;
- foreach my $employee ( @{ $self->employees || [] } ) {
+ foreach my $employee ( @{ $self->employees } ) {
$employee->employer($self);
}
}
after 'employees' => sub {
my ( $self, $employees ) = @_;
- foreach my $employee ( @{ $employees || [] } ) {
+ return unless $employees;
+ foreach my $employee ( @$employees ) {
$employee->employer($self);
}
};
already happened, so we know that if C<$employees> is defined it will contain
an array reference of C<Employee> objects.
+Note that C<employees> is a read/write accessor, so we must return early if
+it's called as a reader.
+
The B<Person> class does not really demonstrate anything new. It has several
C<required> attributes. It also has a C<predicate> method, which we
-first used in L<recipe 3|Moose::Cookbook::Basics::Recipe3>.
+first used in L<Moose::Cookbook::Basics::BinaryTree_AttributeFeatures>.
The only new feature in the C<Employee> class is the C<override>
method modifier:
container type, and instead you will have a new type named
"ArrayRef[]", which doesn't make any sense.
-=item (3)
-
-The C<BUILD> method is actually called by C<< Moose::Object->new >>. It climbs
-the object inheritance graph and calls any C<BUILD> methods it finds in the
-correct order.
-
=back
=begin testing