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