bump copyright date to 2009
[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;
a39ea7dc 12
446e850f 13 requires 'equal_to';
a39ea7dc 14
15 sub not_equal_to {
16 my ( $self, $other ) = @_;
9e93dd19 17 not $self->equal_to($other);
a7d0cd00 18 }
a39ea7dc 19
9e93dd19 20 package Comparable;
a7d0cd00 21 use Moose::Role;
a39ea7dc 22
446e850f 23 with 'Eq';
a39ea7dc 24
446e850f 25 requires 'compare';
a39ea7dc 26
446e850f 27 sub equal_to {
a39ea7dc 28 my ( $self, $other ) = @_;
446e850f 29 $self->compare($other) == 0;
a39ea7dc 30 }
31
446e850f 32 sub greater_than {
a39ea7dc 33 my ( $self, $other ) = @_;
446e850f 34 $self->compare($other) == 1;
a39ea7dc 35 }
36
446e850f 37 sub less_than {
a39ea7dc 38 my ( $self, $other ) = @_;
446e850f 39 $self->compare($other) == -1;
a7d0cd00 40 }
a39ea7dc 41
446e850f 42 sub greater_than_or_equal_to {
a39ea7dc 43 my ( $self, $other ) = @_;
446e850f 44 $self->greater_than($other) || $self->equal_to($other);
a39ea7dc 45 }
46
446e850f 47 sub less_than_or_equal_to {
a39ea7dc 48 my ( $self, $other ) = @_;
446e850f 49 $self->less_than($other) || $self->equal_to($other);
a39ea7dc 50 }
51
9e93dd19 52 package Printable;
9e93dd19 53 use Moose::Role;
a39ea7dc 54
55 requires 'to_string';
56
446e850f 57 package US::Currency;
a7d0cd00 58 use Moose;
a39ea7dc 59
9e93dd19 60 with 'Comparable', 'Printable';
a39ea7dc 61
62 has 'amount' => ( is => 'rw', isa => 'Num', default => 0 );
63
446e850f 64 sub compare {
a39ea7dc 65 my ( $self, $other ) = @_;
446e850f 66 $self->amount <=> $other->amount;
67 }
a39ea7dc 68
9e93dd19 69 sub to_string {
70 my $self = shift;
a39ea7dc 71 sprintf '$%0.2f USD' => $self->amount;
9e93dd19 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 {
a39ea7dc 122 my ( $self, $other ) = @_;
cb26ee7e 123 $self->compare($other) == 0;
124 }
a39ea7dc 125
cb26ee7e 126 sub greater_than {
a39ea7dc 127 my ( $self, $other ) = @_;
cb26ee7e 128 $self->compare($other) == 1;
a39ea7dc 129 }
130
cb26ee7e 131 sub less_than {
a39ea7dc 132 my ( $self, $other ) = @_;
cb26ee7e 133 $self->compare($other) == -1;
134 }
a39ea7dc 135
cb26ee7e 136 sub greater_than_or_equal_to {
a39ea7dc 137 my ( $self, $other ) = @_;
cb26ee7e 138 $self->greater_than($other) || $self->equal_to($other);
a39ea7dc 139 }
140
cb26ee7e 141 sub less_than_or_equal_to {
a39ea7dc 142 my ( $self, $other ) = @_;
cb26ee7e 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
a39ea7dc 163 has 'amount' => ( is => 'rw', isa => 'Num', default => 0 );
cb26ee7e 164
165Now we come to the core of the class. First up, we define a C<compare> method:
166
167 sub compare {
a39ea7dc 168 my ( $self, $other ) = @_;
cb26ee7e 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;
a39ea7dc 183 sprintf '$%0.2f USD' => $self->amount;
cb26ee7e 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
2840a3b2 209Copyright 2006-2009 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
a39ea7dc 216=cut