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