recipe-1
[gitmo/Moose.git] / lib / Moose / Cookbook / Recipe1.pod
CommitLineData
471c4f09 1
2=pod
3
4=head1 NAME
5
cdcae970 6Moose::Cookbook::Recipe1 - The (always classic) cartesian point example.
471c4f09 7
8=head1 SYNOPSIS
9
10 package Point;
11 use strict;
12 use warnings;
13 use Moose;
14
15 has 'x' => (isa => 'Int', is => 'ro');
16 has 'y' => (isa => 'Int', is => 'rw');
17
18 sub clear {
19 my $self = shift;
20 $self->{x} = 0;
21 $self->y(0);
22 }
23
24 package Point3D;
25 use strict;
26 use warnings;
27 use Moose;
28
29 extends 'Point';
30
31 has 'z' => (isa => 'Int');
32
33 after 'clear' => sub {
34 my $self = shift;
35 $self->{z} = 0;
36 };
37
38=head1 DESCRIPTION
39
cdcae970 40This is the classic Point example. This one in particular I took
41from the Perl 6 Apocalypse 12 document, but it is similar to the
42example found in the classic K&R C book as well, and many other
43places. And now, onto the code:
44
45As with all Perl 5 classes, a Moose class is defined in a package.
46Of course we always use C<strict> and C<warnings> (don't forget
47that a kitten will die if you don't) and then we C<use Moose>.
48
49By loading Moose, we are enabeling the Moose "environment" to be
50loaded within our package. This means that we export some functions
51which serve as Moose "keywords". This is nothing fancier than that,
52just plain old exported functions.
53
54Another important thing happens at this stage as well. Moose will
55automatically set your package's superclass to be L<Moose::Object>.
56The reason we do this, is so that we can be sure that you will
57inherit from L<Moose::Object> and get the benefits that provides
58(see the L<Moose::Object> for those details). However, you don't
59actually I<have> to inherit from L<Moose::Object> if you don't
60want to, all other features of Moose are still accessible to you.
61
62Now, onto the keywords. The first one we see here is C<has>, which
63defines an instance attribute in your class.
64
65 has 'x' => (isa => 'Int', is => 'ro');
66
67This will create an attribute named C<x>, it will expect that the
68value stored in the attribute to pass the type constraint C<Int> (1),
69and the accessor generated for this attribute will be read-only
70(abbreviated as C<ro>).
71
72The next C<has> line is very similar, with only one difference.
73
74 has 'y' => (isa => 'Int', is => 'rw');
75
76For the C<y> attribute a read/write accessor will be generated
77(abbreviated as C<rw>).
78
79At this point the attributes have been defined, and it is time to
80define our methods. In Moose, as with regular Perl 5 OO, a method
81is just a subroutine defined within the package. So here we create
82the C<clear> method.
83
84 sub clear {
85 my $self = shift;
86 $self->{x} = 0;
87 $self->y(0);
88 }
89
90It is pretty standard, the only thing to note is that we are directly
91accessing the C<x> slot in the instance L<(2)>. This is because the
92value was created with a read-only accessor. This also shows that Moose
93objects are not anything out of the ordinary, but just regular old
94blessed HASH references. This means they are very compatible with
95other Perl 5 (non-Moose) classes as well.
96
97The next part of the code to review is the B<Point> subclass,
98B<Point3D>. The first item you might notice is that we do not use
99the standard C<use base> declaration here. Instead we use the Moose
100keyword C<extends> like so:
101
102 extends 'Point';
103
104This keyword will function very much like C<use base> does in that
105it will make an attempt to load your class if it has not already been
106loaded. However, it differs on one important point. The C<extends>
107keyword will overwrite any previous values in your package's C<@ISA>,
108where C<use base> will C<push> values onto the package's C<@ISA>. It
109is my opinion that the behavior of C<extends> is more intuitive in
110that it is more explicit about defining the superclass relationship.
111
112A small digression here, both Moose and C<extends> support multiple
113inheritence. You simply pass all the superclasses to C<extends>,
114like so:
115
116 extends 'Foo', 'Bar', 'Baz';
117
118Now, back to our B<Point3D> class. The next thing we do is to create
119a new attribute for B<Point3D> called C<z>.
120
121 has 'z' => (isa => 'Int');
122
123As with B<Point>'s C<x> and C<y> attributes, this attribute has a
124type constraint of C<Int>, but it differs in that it does B<not>
125ask for any autogenerated accessors. The result being (aside from
126breaking object encapsulation), that C<x> is a private attribute.
127
128Next comes another Moose feature which we call method "modifiers"
129(or method "advice" for the AOP inclined). The modifier used here
130is the C<after> modifier, and looks like this:
131
132 after 'clear' => sub {
133 my $self = shift;
134 $self->{z} = 0;
135 };
136
137This modifier tells Moose to install a C<clear> method for
138B<Point3D> that will first run the C<clear> method for the
139superclass (in this case C<Point::clear>), and then run this
140method I<after> it (passing in the same arguments as the original
141method).
142
143Now, of course using the C<after> modifier is not the only way to
144accomplish this. I mean, after all, this B<is> Perl right? You
145would get the same results with this code:
146
147 sub clear {
148 my $self = shift;
149 $self->SUPER::clear();
150 $self->{z} = 0;
151 }
152
153You could also use another Moose method modifier, C<override> here,
154and get the same results again. Here is how that would look.
155
156 override 'clear' => sub {
157 my $self = shift;
158 super();
159 $self->{z} = 0;
160 };
161
162The C<override> modifier allows you to use the C<super> keyword
163within it to dispatch to the superclass's method in a very Ruby-ish
164style.
165
166Now of course, what use is a class if you cant instantiate objects
167with it. Now since B<Point> inherits from L<Moose::Object>, it will
168inherit the default L<Moose::Object> constructor called C<new>. Here
169are two examples of how that is used:
170
171 my $point = Point->new(x => 1, y => 2);
172 my $point3d = Point3D->new(x => 1, y => 2, z => 3);
173
174As you can see, C<new> accepts named argument pairs for any of the
175attributes. It does not I<require> that you pass in the all the
176attributes, and it will politely ignore any named arguments it does
177not recognize.
178
179From here, you can use C<$point> and C<$point3d> just as you would
180any other Perl 5 object.
181
182=head1 CONCLUSION
183
184I hope this recipe has given you some explaination of how to use
185Moose to build you Perl 5 classes. The next recipe will build upon
186the basics shown here with more complex attributes and methods.
187Please read on :)
188
189=head1 FOOTNOTES
190
191=over 4
192
193=item (1)
194
195Several default type constraints are provided by Moose, of which
196C<Int> is one. For more information on the built-in type constraints
197and the type constraint system in general, see the
198L<Moose::Util::TypeConstraints> documentation.
199
200=item (2)
201
202Future plans for Moose include allowing for alternate instance
203structures such as blessed ARRAY refs and such. If you want you Moose
204classes to be interchangable, it is advised that you avoid direct
205instance access, like that which is shown above.
206
207=back
208
209=head1 SEE ALSO
210
211=over 4
212
213=item Method Modifiers
214
215The concept of method modifiers is directly ripped off from CLOS. A
216great explaination of them can be found by following this link.
217
218L<http://www.gigamonkeys.com/book/object-reorientation-generic-functions.html>
219
220=back
221
471c4f09 222=head1 AUTHOR
223
224Stevan Little E<lt>stevan@iinteractive.comE<gt>
225
226=head1 COPYRIGHT AND LICENSE
227
228Copyright 2006 by Infinity Interactive, Inc.
229
230L<http://www.iinteractive.com>
231
232This library is free software; you can redistribute it and/or modify
233it under the same terms as Perl itself.
234
235=cut