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