Commit | Line | Data |
daa0fd7d |
1 | package Moose::Cookbook::Basics::Recipe8; |
1f476b5f |
2 | |
daa0fd7d |
3 | # ABSTRACT: Builder methods and lazy_build |
4 | |
5 | __END__ |
1f476b5f |
6 | |
1f476b5f |
7 | |
daa0fd7d |
8 | =pod |
1f476b5f |
9 | |
10 | =head1 SYNOPSIS |
11 | |
12 | package BinaryTree; |
13 | use Moose; |
14 | |
15 | has 'node' => (is => 'rw', isa => 'Any'); |
16 | |
17 | has 'parent' => ( |
18 | is => 'rw', |
19 | isa => 'BinaryTree', |
20 | predicate => 'has_parent', |
21 | weak_ref => 1, |
22 | ); |
23 | |
24 | has 'left' => ( |
25 | is => 'rw', |
26 | isa => 'BinaryTree', |
27 | predicate => 'has_left', |
28 | lazy => 1, |
29 | builder => '_build_child_tree', |
30 | ); |
31 | |
32 | has 'right' => ( |
33 | is => 'rw', |
34 | isa => 'BinaryTree', |
35 | predicate => 'has_right', |
36 | lazy => 1, |
37 | builder => '_build_child_tree', |
38 | ); |
39 | |
40 | before 'right', 'left' => sub { |
41 | my ($self, $tree) = @_; |
42 | $tree->parent($self) if defined $tree; |
43 | }; |
44 | |
45 | sub _build_child_tree { |
46 | my $self = shift; |
47 | |
48 | return BinaryTree->new( parent => $self ); |
49 | } |
50 | |
51 | =head1 DESCRIPTION |
52 | |
53 | If you've already read L<Moose::Cookbook::Basics::Recipe3>, then this |
54 | example should look very familiar. In fact, all we've done here is |
55 | replace the attribute's C<default> parameter with a C<builder>. |
56 | |
57 | In this particular case, the C<default> and C<builder> options act in |
58 | exactly the same way. When the C<left> or C<right> attribute is read, |
59 | Moose calls the builder method to initialize the attribute. |
60 | |
61 | Note that Moose calls the builder method I<on the object which has the |
62 | attribute>. Here's an example: |
63 | |
64 | my $tree = BinaryTree->new(); |
65 | |
66 | my $left = $tree->left(); |
67 | |
68 | When C<< $tree->left() >> is called, Moose calls C<< |
69 | $tree->_build_child_tree() >> in order to populate the C<left> |
70 | attribute. If we had passed C<left> to the original constructor, the |
71 | builder would not be called. |
72 | |
73 | There are some differences between C<default> and C<builder>. Notably, |
74 | a builder is subclassable, and can be composed from a role. See |
75 | L<Moose::Manual::Attributes> for more details. |
76 | |
77 | =head2 The lazy_build shortcut |
78 | |
79 | The C<lazy_build> attribute option can be used as sugar to specify |
80 | a whole set of attribute options at once: |
81 | |
82 | has 'animal' => ( |
83 | is => 'ro', |
84 | isa => 'Animal', |
85 | lazy_build => 1, |
86 | ); |
87 | |
88 | This is a shorthand for: |
89 | |
90 | has 'animal' => ( |
91 | is => 'ro', |
92 | isa => 'Animal', |
93 | required => 1, |
94 | lazy => 1, |
95 | builder => '_build_animal', |
96 | predicate => 'has_animal', |
97 | clearer => 'clear_animal', |
98 | ); |
99 | |
100 | If your attribute starts with an underscore, Moose is smart and will |
101 | do the right thing with the C<predicate> and C<clearer>, making them |
102 | both start with an underscore. The C<builder> method I<always> starts |
103 | with an underscore. |
104 | |
970a92fa |
105 | You can read more about C<lazy_build> in L<Moose::Meta::Attribute> |
1f476b5f |
106 | |
107 | =head1 CONCLUSION |
108 | |
109 | The C<builder> option is a more OO-friendly version of the C<default> |
110 | functionality. It also separates the default-generating code into a |
111 | well-defined method. Sprinkling your attribute definitions with |
112 | anonymous subroutines can be quite ugly and hard to follow. |
113 | |
1f476b5f |
114 | =cut |