Commit | Line | Data |
471c4f09 |
1 | |
2 | =pod |
3 | |
4 | =head1 NAME |
5 | |
3824830b |
6 | Moose::Cookbook::Recipe1 - The (always classic) B<Point> example. |
471c4f09 |
7 | |
8 | =head1 SYNOPSIS |
9 | |
10 | package Point; |
471c4f09 |
11 | use Moose; |
12 | |
bcbaa845 |
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 | } |
471c4f09 |
21 | |
22 | sub clear { |
23 | my $self = shift; |
24 | $self->{x} = 0; |
25 | $self->y(0); |
26 | } |
27 | |
28 | package Point3D; |
471c4f09 |
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 | |
cdcae970 |
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. |
a9eca7df |
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. |
cdcae970 |
50 | |
a9eca7df |
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. |
cdcae970 |
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>. |
a9eca7df |
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 |
cdcae970 |
61 | actually I<have> to inherit from L<Moose::Object> if you don't |
a9eca7df |
62 | want to. All Moose features will still be accessible to you. |
cdcae970 |
63 | |
64 | Now, onto the keywords. The first one we see here is C<has>, which |
a9eca7df |
65 | defines an instance attribute in your class: |
cdcae970 |
66 | |
67 | has 'x' => (isa => 'Int', is => 'ro'); |
68 | |
a9eca7df |
69 | This will create an attribute named C<x>, which will expect the |
cdcae970 |
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 | |
a9eca7df |
74 | The next C<has> line is very similar, with only one difference: |
cdcae970 |
75 | |
76 | has 'y' => (isa => 'Int', is => 'rw'); |
77 | |
a9eca7df |
78 | A read/write (abbreviated as C<rw>) accessor will be generated for |
79 | the C<y> attribute. |
cdcae970 |
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 | |
a9eca7df |
114 | A small digression here: both Moose and C<extends> support multiple |
4711f5f7 |
115 | inheritance. You simply pass all the superclasses to C<extends>, |
cdcae970 |
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 |
a9eca7df |
128 | broken object encapsulation) that C<x> is a private attribute. |
cdcae970 |
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, |
a9eca7df |
156 | and get the same results again. Here is how that would look: |
cdcae970 |
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 | |
a9eca7df |
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 |
cdcae970 |
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 | |
703d9522 |
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 |
db1ab48d |
183 | done, you can refer to the F<t/001_recipe.t> test file. |
cdcae970 |
184 | |
185 | =head1 CONCLUSION |
186 | |
4711f5f7 |
187 | I hope this recipe has given you some explanation of how to use |
a9eca7df |
188 | Moose to build your Perl 5 classes. The next recipe will build upon |
cdcae970 |
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 |
a9eca7df |
199 | C<Int> is one. For more information on the builtin type constraints |
cdcae970 |
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 |
a9eca7df |
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. |
cdcae970 |
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 |
4711f5f7 |
219 | great explanation of them can be found by following this link. |
cdcae970 |
220 | |
221 | L<http://www.gigamonkeys.com/book/object-reorientation-generic-functions.html> |
222 | |
223 | =back |
224 | |
471c4f09 |
225 | =head1 AUTHOR |
226 | |
227 | Stevan Little E<lt>stevan@iinteractive.comE<gt> |
228 | |
229 | =head1 COPYRIGHT AND LICENSE |
230 | |
b77fdbed |
231 | Copyright 2006, 2007 by Infinity Interactive, Inc. |
471c4f09 |
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 |