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