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