Commit | Line | Data |
53a1e093 |
1 | package Moose::Cookbook::Basics::BinaryTree_BuilderAndLazyBuild; |
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 | |
ed82277c |
53 | If you've already read |
54 | L<Moose::Cookbook::Basics::BinaryTree_AttributeFeatures>, then this example |
55 | should look very familiar. In fact, all we've done here is replace the |
56 | attribute's C<default> parameter with a C<builder>. |
1f476b5f |
57 | |
58 | In this particular case, the C<default> and C<builder> options act in |
59 | exactly the same way. When the C<left> or C<right> attribute is read, |
60 | Moose calls the builder method to initialize the attribute. |
61 | |
62 | Note that Moose calls the builder method I<on the object which has the |
63 | attribute>. Here's an example: |
64 | |
65 | my $tree = BinaryTree->new(); |
66 | |
67 | my $left = $tree->left(); |
68 | |
69 | When C<< $tree->left() >> is called, Moose calls C<< |
70 | $tree->_build_child_tree() >> in order to populate the C<left> |
71 | attribute. If we had passed C<left> to the original constructor, the |
72 | builder would not be called. |
73 | |
74 | There are some differences between C<default> and C<builder>. Notably, |
75 | a builder is subclassable, and can be composed from a role. See |
76 | L<Moose::Manual::Attributes> for more details. |
77 | |
78 | =head2 The lazy_build shortcut |
79 | |
80 | The C<lazy_build> attribute option can be used as sugar to specify |
81 | a whole set of attribute options at once: |
82 | |
83 | has 'animal' => ( |
84 | is => 'ro', |
85 | isa => 'Animal', |
86 | lazy_build => 1, |
87 | ); |
88 | |
89 | This is a shorthand for: |
90 | |
91 | has 'animal' => ( |
92 | is => 'ro', |
93 | isa => 'Animal', |
94 | required => 1, |
95 | lazy => 1, |
96 | builder => '_build_animal', |
97 | predicate => 'has_animal', |
98 | clearer => 'clear_animal', |
99 | ); |
100 | |
101 | If your attribute starts with an underscore, Moose is smart and will |
102 | do the right thing with the C<predicate> and C<clearer>, making them |
103 | both start with an underscore. The C<builder> method I<always> starts |
104 | with an underscore. |
105 | |
970a92fa |
106 | You can read more about C<lazy_build> in L<Moose::Meta::Attribute> |
1f476b5f |
107 | |
108 | =head1 CONCLUSION |
109 | |
110 | The C<builder> option is a more OO-friendly version of the C<default> |
111 | functionality. It also separates the default-generating code into a |
112 | well-defined method. Sprinkling your attribute definitions with |
113 | anonymous subroutines can be quite ugly and hard to follow. |
114 | |
1f476b5f |
115 | =cut |