Merge branch 'master' into method_generation_cleanup
[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;
59f5bbde 12
446e850f 13 requires 'equal_to';
59f5bbde 14
15 sub not_equal_to {
16 my ( $self, $other ) = @_;
9e93dd19 17 not $self->equal_to($other);
a7d0cd00 18 }
59f5bbde 19
9e93dd19 20 package Comparable;
a7d0cd00 21 use Moose::Role;
59f5bbde 22
446e850f 23 with 'Eq';
59f5bbde 24
446e850f 25 requires 'compare';
59f5bbde 26
446e850f 27 sub equal_to {
59f5bbde 28 my ( $self, $other ) = @_;
446e850f 29 $self->compare($other) == 0;
59f5bbde 30 }
31
446e850f 32 sub greater_than {
59f5bbde 33 my ( $self, $other ) = @_;
446e850f 34 $self->compare($other) == 1;
59f5bbde 35 }
36
446e850f 37 sub less_than {
59f5bbde 38 my ( $self, $other ) = @_;
446e850f 39 $self->compare($other) == -1;
a7d0cd00 40 }
59f5bbde 41
446e850f 42 sub greater_than_or_equal_to {
59f5bbde 43 my ( $self, $other ) = @_;
446e850f 44 $self->greater_than($other) || $self->equal_to($other);
59f5bbde 45 }
46
446e850f 47 sub less_than_or_equal_to {
59f5bbde 48 my ( $self, $other ) = @_;
446e850f 49 $self->less_than($other) || $self->equal_to($other);
59f5bbde 50 }
51
9e93dd19 52 package Printable;
9e93dd19 53 use Moose::Role;
59f5bbde 54
55 requires 'to_string';
56
446e850f 57 package US::Currency;
a7d0cd00 58 use Moose;
59f5bbde 59
9e93dd19 60 with 'Comparable', 'Printable';
59f5bbde 61
62 has 'amount' => ( is => 'rw', isa => 'Num', default => 0 );
63
446e850f 64 sub compare {
59f5bbde 65 my ( $self, $other ) = @_;
446e850f 66 $self->amount <=> $other->amount;
67 }
59f5bbde 68
9e93dd19 69 sub to_string {
70 my $self = shift;
59f5bbde 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 {
59f5bbde 122 my ( $self, $other ) = @_;
cb26ee7e 123 $self->compare($other) == 0;
124 }
59f5bbde 125
cb26ee7e 126 sub greater_than {
59f5bbde 127 my ( $self, $other ) = @_;
cb26ee7e 128 $self->compare($other) == 1;
59f5bbde 129 }
130
cb26ee7e 131 sub less_than {
59f5bbde 132 my ( $self, $other ) = @_;
cb26ee7e 133 $self->compare($other) == -1;
134 }
59f5bbde 135
cb26ee7e 136 sub greater_than_or_equal_to {
59f5bbde 137 my ( $self, $other ) = @_;
cb26ee7e 138 $self->greater_than($other) || $self->equal_to($other);
59f5bbde 139 }
140
cb26ee7e 141 sub less_than_or_equal_to {
59f5bbde 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
59f5bbde 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 {
59f5bbde 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;
59f5bbde 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
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
59f5bbde 216=cut