Commit | Line | Data |
471c4f09 |
1 | |
2 | =pod |
3 | |
4 | =head1 NAME |
5 | |
021b8139 |
6 | Moose::Cookbook::Basics::Recipe1 - The (always classic) B<Point> example. |
471c4f09 |
7 | |
8 | =head1 SYNOPSIS |
9 | |
10 | package Point; |
471c4f09 |
11 | use Moose; |
a34602e7 |
12 | |
13 | has 'x' => (isa => 'Int', is => 'rw', required => 1); |
14 | has 'y' => (isa => 'Int', is => 'rw', required => 1); |
15 | |
471c4f09 |
16 | sub clear { |
17 | my $self = shift; |
a34602e7 |
18 | $self->x(0); |
19 | $self->y(0); |
471c4f09 |
20 | } |
a34602e7 |
21 | |
471c4f09 |
22 | package Point3D; |
471c4f09 |
23 | use Moose; |
a34602e7 |
24 | |
471c4f09 |
25 | extends 'Point'; |
a34602e7 |
26 | |
27 | has 'z' => (isa => 'Int', is => 'rw', required => 1); |
28 | |
471c4f09 |
29 | after 'clear' => sub { |
30 | my $self = shift; |
a34602e7 |
31 | $self->z(0); |
471c4f09 |
32 | }; |
33 | |
d68bf053 |
34 | .... |
35 | |
36 | # hash or hashrefs are ok for the constructor |
37 | my $point1 = Point->new(x => 5, y => 7); |
38 | my $point2 = Point->new({x => 5, y => 7}); |
39 | |
40 | my $point3d = Point3D->new(x => 5, y => 42, z => -5); |
41 | |
471c4f09 |
42 | =head1 DESCRIPTION |
43 | |
a34602e7 |
44 | This is the classic Point example. It is taken directly from the Perl |
45 | 6 Apocalypse 12 document, and is similar to the example found in the |
46 | classic K&R C book as well. |
cdcae970 |
47 | |
a34602e7 |
48 | As with all Perl 5 classes, a Moose class is defined in a package. |
49 | Moose handles turning on C<strict> and C<warnings> for us, so all we |
50 | need to do is say C<use Moose>, and no kittens will die. |
cdcae970 |
51 | |
a34602e7 |
52 | When Moose is loaded, it exports a set of sugar functions into our |
53 | package. This means that we import some functions which serve as Moose |
54 | "keywords". These aren't real language keywords, they're just Perl |
55 | functions exported into our package. |
cdcae970 |
56 | |
a34602e7 |
57 | Moose automatically makes our package a subclass of L<Moose::Object>. |
58 | The L<Moose::Object> class provides us with a constructor that |
59 | respects our attributes, as well other features. See L<Moose::Object> |
60 | for details. |
cdcae970 |
61 | |
a34602e7 |
62 | Now, onto the keywords. The first one we see here is C<has>, which |
63 | defines an instance attribute in our class: |
cdcae970 |
64 | |
a34602e7 |
65 | has 'x' => (isa => 'Int', is => 'rw', required => 1); |
cdcae970 |
66 | |
a34602e7 |
67 | This will create an attribute named C<x>. The C<isa> parameter says |
68 | that we expect the value stored in this attribute to pass the type |
69 | constraint for C<Int> (1). The accessor generated for this attribute |
70 | will be read-write. |
cdcae970 |
71 | |
a34602e7 |
72 | The C<< requires => 1 >> parameter means that this attribute must be |
73 | provided when a new object is created. A point object without |
74 | coordinates doesn't make much sense, so we don't allow it. |
cdcae970 |
75 | |
a34602e7 |
76 | We have defined our attributes; next we define our methods. In Moose, |
77 | as with regular Perl 5 OO, a method is just a subroutine defined |
78 | within the package: |
cdcae970 |
79 | |
80 | sub clear { |
81 | my $self = shift; |
a34602e7 |
82 | $self->x(0); |
83 | $self->y(0); |
cdcae970 |
84 | } |
85 | |
a34602e7 |
86 | That concludes the B<Point> class. |
cdcae970 |
87 | |
a34602e7 |
88 | Next we have a subclass of B<Point>, B<Point3D>. To declare our |
89 | superclass, we use the Moose keyword C<extends>: |
cdcae970 |
90 | |
91 | extends 'Point'; |
92 | |
a34602e7 |
93 | The C<extends> keyword works much like C<use base>. First, it will |
94 | attempt to load your class if needed. However, unlike C<base>, the |
95 | C<extends> keyword will I<overwrite> any previous values in your |
96 | package's C<@ISA>, where C<use base> will C<push> values onto the |
97 | package's C<@ISA>. |
cdcae970 |
98 | |
a34602e7 |
99 | It is my opinion that the behavior of C<extends> is more intuitive. |
100 | (2). |
cdcae970 |
101 | |
a34602e7 |
102 | Next we create a new attribute for B<Point3D> called C<z>. |
cdcae970 |
103 | |
a34602e7 |
104 | has 'z' => (isa => 'Int', is => 'rw', required => 1); |
cdcae970 |
105 | |
a34602e7 |
106 | This attribute is just like B<Point>'s C<x> and C<y> attributes. |
cdcae970 |
107 | |
a34602e7 |
108 | The C<after> keyword demonstrates a Moose feature called "method |
109 | modifiers" (or "advice" for the AOP inclined): |
cdcae970 |
110 | |
111 | after 'clear' => sub { |
112 | my $self = shift; |
a34602e7 |
113 | $self->z(0); |
cdcae970 |
114 | }; |
115 | |
a34602e7 |
116 | When C<clear> is called on a B<Point3D> object, our modifier method |
117 | gets called as well. Unsurprisingly, the modifier is called I<after> |
118 | the real method. |
119 | |
120 | In this case, the real C<clear> method is inherited from B<Point>. Our |
121 | modifier method receives the same arguments as those passed to the |
122 | modified method (just C<$self> here). |
cdcae970 |
123 | |
a34602e7 |
124 | Of course, using the C<after> modifier is not the only way to |
125 | accomplish this. This B<is> Perl, right? You can get the same results |
126 | with this code: |
cdcae970 |
127 | |
128 | sub clear { |
129 | my $self = shift; |
130 | $self->SUPER::clear(); |
a34602e7 |
131 | $self->z(0); |
cdcae970 |
132 | } |
133 | |
a34602e7 |
134 | You could also use another Moose method modifier, C<override>: |
cdcae970 |
135 | |
136 | override 'clear' => sub { |
137 | my $self = shift; |
138 | super(); |
a34602e7 |
139 | $self->z(0); |
cdcae970 |
140 | }; |
cdcae970 |
141 | |
a34602e7 |
142 | The C<override> modifier allows you to use the C<super> keyword to |
143 | dispatch to the superclass's method in a very Ruby-ish style. |
cdcae970 |
144 | |
a34602e7 |
145 | The choice of whether to use a method modifier, and which one to use, |
146 | is often a question of style as much as functionality. |
147 | |
148 | Since B<Point> inherits from L<Moose::Object>, it will also inherit |
149 | the default L<Moose::Object> constructor: |
150 | |
d68bf053 |
151 | my $point1 = Point->new(x => 5, y => 7); |
152 | my $point2 = Point->new({x => 5, y => 7}); |
153 | |
154 | my $point3d = Point3D->new(x => 5, y => 42, z => -5); |
cdcae970 |
155 | |
a34602e7 |
156 | The C<new> constructor accepts a named argument pair for each |
d68bf053 |
157 | attribute defined by the class, which you can provide as a hash or |
158 | hash reference. In this particular example, the attributes are |
159 | required, and calling C<new> without them will throw an error. |
160 | |
161 | my $point = Point->new( x => 5 ); # no y, kaboom! |
a34602e7 |
162 | |
163 | From here on, we can use C<$point> and C<$point3d> just as you would |
164 | any other Perl 5 object. For a more detailed example of what can be |
165 | done, you can refer to the F<t/000_recipes/basic/001_point.t> test |
166 | file. |
167 | |
168 | =head2 Moose Objects are Just Hashrefs |
169 | |
170 | While this all may appear rather magical, it's important to realize |
171 | that Moose objects are just hash references under the hood (3). For |
172 | example, you could pass C<$self> to C<Data::Dumper> and you'd get |
173 | exactly what you'd expect. |
cdcae970 |
174 | |
a34602e7 |
175 | You could even poke around inside the object's data structure, but |
176 | that is strongly discouraged. |
177 | |
178 | The fact that Moose objects are hashrefs means it is easy to use Moose |
179 | to extend non-Moose classes, as long as they too are hash |
180 | references. If you want to extend a non-hashref class, check out |
181 | C<MooseX::InsideOut>. |
cdcae970 |
182 | |
183 | =head1 CONCLUSION |
184 | |
a34602e7 |
185 | This recipe demonstrates some basic Moose concepts. The next recipe |
186 | will build upon the basics shown here with more complex attributes and |
187 | methods. Please read on :) |
cdcae970 |
188 | |
189 | =head1 FOOTNOTES |
190 | |
191 | =over 4 |
192 | |
193 | =item (1) |
194 | |
a34602e7 |
195 | Moose provides a number of builtin type constraints are provided by, |
196 | of which C<Int> is one. For more information on the type constraint |
197 | system, see L<Moose::Util::TypeConstraints>. |
cdcae970 |
198 | |
199 | =item (2) |
200 | |
a34602e7 |
201 | The C<extends> keyword support multiple inheritance. Simply pass all |
202 | of your superclasses to C<extends> as a list: |
203 | |
204 | extends 'Foo', 'Bar', 'Baz'; |
205 | |
206 | =item (3) |
207 | |
1eca36fc |
208 | Moose supports using instance structures other than blessed hash |
a34602e7 |
209 | references (such as in a glob reference - see |
210 | L<MooseX::GlobRef::Object>). |
cdcae970 |
211 | |
212 | =back |
213 | |
214 | =head1 SEE ALSO |
215 | |
216 | =over 4 |
217 | |
218 | =item Method Modifiers |
219 | |
220 | The concept of method modifiers is directly ripped off from CLOS. A |
4711f5f7 |
221 | great explanation of them can be found by following this link. |
cdcae970 |
222 | |
223 | L<http://www.gigamonkeys.com/book/object-reorientation-generic-functions.html> |
224 | |
225 | =back |
226 | |
471c4f09 |
227 | =head1 AUTHOR |
228 | |
229 | Stevan Little E<lt>stevan@iinteractive.comE<gt> |
230 | |
231 | =head1 COPYRIGHT AND LICENSE |
232 | |
778db3ac |
233 | Copyright 2006-2008 by Infinity Interactive, Inc. |
471c4f09 |
234 | |
235 | L<http://www.iinteractive.com> |
236 | |
237 | This library is free software; you can redistribute it and/or modify |
238 | it under the same terms as Perl itself. |
239 | |
a34602e7 |
240 | =cut |