Merge branch 'master' into method_generation_cleanup
[gitmo/Moose.git] / lib / Moose / Cookbook / Roles / Recipe1.pod
1
2 =pod
3
4 =head1 NAME
5
6 Moose::Cookbook::Roles::Recipe1 - The Moose::Role example
7
8 =head1 SYNOPSIS
9
10   package Eq;
11   use Moose::Role;
12
13   requires 'equal_to';
14
15   sub not_equal_to {
16       my ( $self, $other ) = @_;
17       not $self->equal_to($other);
18   }
19
20   package Comparable;
21   use Moose::Role;
22
23   with 'Eq';
24
25   requires 'compare';
26
27   sub equal_to {
28       my ( $self, $other ) = @_;
29       $self->compare($other) == 0;
30   }
31
32   sub greater_than {
33       my ( $self, $other ) = @_;
34       $self->compare($other) == 1;
35   }
36
37   sub less_than {
38       my ( $self, $other ) = @_;
39       $self->compare($other) == -1;
40   }
41
42   sub greater_than_or_equal_to {
43       my ( $self, $other ) = @_;
44       $self->greater_than($other) || $self->equal_to($other);
45   }
46
47   sub less_than_or_equal_to {
48       my ( $self, $other ) = @_;
49       $self->less_than($other) || $self->equal_to($other);
50   }
51
52   package Printable;
53   use Moose::Role;
54
55   requires 'to_string';
56
57   package US::Currency;
58   use Moose;
59
60   with 'Comparable', 'Printable';
61
62   has 'amount' => ( is => 'rw', isa => 'Num', default => 0 );
63
64   sub compare {
65       my ( $self, $other ) = @_;
66       $self->amount <=> $other->amount;
67   }
68
69   sub to_string {
70       my $self = shift;
71       sprintf '$%0.2f USD' => $self->amount;
72   }
73
74 =head1 DESCRIPTION
75
76 In this recipe we examine the role support provided in Moose. "Roles" may be
77 described in many ways, but there are two main ways in which they are used: as
78 interfaces, and as a means of code reuse. This recipe demonstrates the
79 construction and incorporation of roles that define comparison and display of
80 objects.
81
82 Let's start by examining B<Eq>. You'll notice that instead of the familiar C<use
83 Moose> you might be expecting, here we use C<Moose::Role> to make it clear that
84 this is a role. We encounter a new keyword, C<requires>:
85
86   requires 'equal_to';
87
88 What this does is to indicate that any class which "consumes" (that is to say,
89 "includes using C<with>", as we'll see a little later) the B<Eq> role I<must>
90 include an C<equal_to> method, whether this is provided by the class itself, one
91 of its superclasses, or another role consumed by the class (1).
92
93 In addition to requiring an C<equal_to> method, B<Eq> defines a C<not_equal_to>
94 method, which simply inverts the result of C<equal_to>. Defining additional
95 methods in this way, by using only a few base methods that target classes must
96 define, is a useful pattern to provide maximum functionality with minimum
97 effort.
98
99 After the minimal B<Eq>, we next move on to B<Comparable>. The first thing you
100 will notice is another new keyword, C<with>:
101
102   with 'Eq';
103
104 C<with> is used to provide a list of roles which this class (or role) consumes.
105 Here, B<Comparable> only consumes one role (B<Eq>). In effect, it is as if we
106 defined a C<not_equal_to> method within Comparable, and also promised to fulfill
107 the requirement of an C<equal_to> method.
108
109 B<Comparable> itself states that it requires C<compare>. Again, it means that
110 any classes consuming this role must implement a C<compare> method.
111
112   requires 'compare';
113
114 B<Comparable> defines an C<equal_to> method which satisfies the B<Eq> role's
115 requirements. This, along with a number of other methods (C<greater_than>,
116 C<less_than>, C<greater_than_or_equal_to>, and C<less_than_or_equal_to>) is
117 simply defined in terms of C<compare>, once again demonstrating the pattern of
118 defining a number of utility methods in terms of only a single method that the
119 target class need implement.
120
121   sub equal_to {
122       my ( $self, $other ) = @_;
123       $self->compare($other) == 0;
124   }
125
126   sub greater_than {
127       my ( $self, $other ) = @_;
128       $self->compare($other) == 1;
129   }
130
131   sub less_than {
132       my ( $self, $other ) = @_;
133       $self->compare($other) == -1;
134   }
135
136   sub greater_than_or_equal_to {
137       my ( $self, $other ) = @_;
138       $self->greater_than($other) || $self->equal_to($other);
139   }
140
141   sub less_than_or_equal_to {
142       my ( $self, $other ) = @_;
143       $self->less_than($other) || $self->equal_to($other);
144   }
145
146 Next up is B<Printable>. This is a very simple role, akin to B<Eq>. It merely
147 requires a C<to_string> method. Roles that only require methods are very much
148 like Java's interfaces. If we know that a class does the B<Printable> role, it
149 not only tells us that we can call the C<to_string> method on it, but also that
150 C<to_string> has the precise semantics we want (consider classes B<Tree> and
151 B<Dog>, both with method C<bark>).
152
153 Finally, we come to B<US::Currency>, a class that allows us to reap the benefits
154 of our hard work. This is a regular Moose class, so we include the normal C<use
155 Moose>. It consumes both B<Comparable> and B<Printable>, as the following line
156 shows:
157
158   with 'Comparable', 'Printable';
159
160 It also defines a regular Moose attribute, C<amount>, with a type constraint of
161 C<Num> and a default of C<0>:
162
163   has 'amount' => ( is => 'rw', isa => 'Num', default => 0 );
164
165 Now we come to the core of the class. First up, we define a C<compare> method:
166
167   sub compare {
168       my ( $self, $other ) = @_;
169       $self->amount <=> $other->amount;
170   }
171
172 As you can see, it simply compares the C<amount> attribute of this object with
173 the C<amount> attribute of the other object passed to it. With the single
174 definition of this method, we gain the following methods for free: C<equal_to>,
175 C<greater_than>, C<less_than>, C<greater_than_or_equal_to> and
176 C<less_than_or_equal_to>.
177
178 We end the class with a definition of the C<to_string> method, which formats the
179 C<amount> attribute for display:
180
181   sub to_string {
182       my $self = shift;
183       sprintf '$%0.2f USD' => $self->amount;
184   }
185
186 =head1 CONCLUSION
187
188 This recipe has shown that roles can be very powerful and immensely useful, and
189 save a great deal of repetition.
190
191 =head1 FOOTNOTES
192
193 =over 4
194
195 =item (1)
196
197 At present, method requirements from roles cannot be satisfied by attribute
198 accessors. This is a limitation of Moose, and will most likely be rectified in a
199 future release.
200
201 =back
202
203 =head1 AUTHOR
204
205 Stevan Little E<lt>stevan@iinteractive.comE<gt>
206
207 =head1 COPYRIGHT AND LICENSE
208
209 Copyright 2006-2008 by Infinity Interactive, Inc.
210
211 L<http://www.iinteractive.com>
212
213 This library is free software; you can redistribute it and/or modify
214 it under the same terms as Perl itself.
215
216 =cut