edtis
[gitmo/Moose.git] / lib / Moose / Cookbook / Recipe1.pod
CommitLineData
471c4f09 1
2=pod
3
4=head1 NAME
5
3824830b 6Moose::Cookbook::Recipe1 - The (always classic) B<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
703d9522 179From here on, you can use C<$point> and C<$point3d> just as you would
180any other Perl 5 object. For a more detailed example of what can be
181done, you can refer to the F<t/001_basic.t> test file.
cdcae970 182
183=head1 CONCLUSION
184
185I hope this recipe has given you some explaination of how to use
186Moose to build you Perl 5 classes. The next recipe will build upon
187the basics shown here with more complex attributes and methods.
188Please read on :)
189
190=head1 FOOTNOTES
191
192=over 4
193
194=item (1)
195
196Several default type constraints are provided by Moose, of which
197C<Int> is one. For more information on the built-in type constraints
198and the type constraint system in general, see the
199L<Moose::Util::TypeConstraints> documentation.
200
201=item (2)
202
203Future plans for Moose include allowing for alternate instance
204structures such as blessed ARRAY refs and such. If you want you Moose
205classes to be interchangable, it is advised that you avoid direct
206instance access, like that which is shown above.
207
208=back
209
210=head1 SEE ALSO
211
212=over 4
213
214=item Method Modifiers
215
216The concept of method modifiers is directly ripped off from CLOS. A
217great explaination of them can be found by following this link.
218
219L<http://www.gigamonkeys.com/book/object-reorientation-generic-functions.html>
220
221=back
222
471c4f09 223=head1 AUTHOR
224
225Stevan Little E<lt>stevan@iinteractive.comE<gt>
226
227=head1 COPYRIGHT AND LICENSE
228
229Copyright 2006 by Infinity Interactive, Inc.
230
231L<http://www.iinteractive.com>
232
233This library is free software; you can redistribute it and/or modify
234it under the same terms as Perl itself.
235
236=cut