Commit | Line | Data |
ecd7cc3e |
1 | =pod |
2 | |
3 | =head1 NAME |
4 | |
5 | Moose::Manual::Types - Moose's Type System |
6 | |
7 | =head1 TYPES IN PERL? |
8 | |
9 | Moose provides its own type system for your class's attributes. You |
10 | can also use these types to validate method parameters with the help |
11 | of some MooseX modules. |
12 | |
13 | Moose's type system is based on a combination of Perl 5's own |
14 | I<implicit> types, and some Perl 6 concepts as well. But most |
15 | importantly, you can easily create your own subtypes with custom |
16 | constraints, making it easy to express any sort of validation. |
17 | |
18 | You can also name types and re-use them by name, making it easy to |
19 | share types throughout a large application. |
20 | |
21 | Let us be clear that is not a "real" type system. Moose does not |
22 | magically make Perl start associating types with variables. In many |
23 | ways, this is really an advanced parameter checking system which |
24 | allows you to associate a name with a constraintq. |
25 | |
26 | That said, it's still pretty damn useful, and we think it's one of the |
27 | things that makes Moose both fun and powerful. Taking advantage of the |
28 | type system makes it much easier to ensure that you are getting valid |
29 | data, and it also contributes greatly to code maintainability. |
30 | |
31 | =head1 THE TYPES |
32 | |
33 | The basic Moose type hierarchy looks like this |
34 | |
35 | Any |
36 | Item |
37 | Bool |
38 | Maybe[`a] |
39 | Undef |
40 | Defined |
41 | Value |
42 | Num |
43 | Int |
44 | Str |
45 | ClassName |
46 | Ref |
47 | ScalarRef |
48 | ArrayRef[`a] |
49 | HashRef[`a] |
50 | CodeRef |
51 | RegexpRef |
52 | GlobRef |
53 | FileHandle |
54 | Object |
55 | Role |
56 | |
57 | In practice, the only difference between C<Any> and C<Item> is |
58 | conceptual. C<Item> is used as the top-level type in the hierarchy. |
59 | |
60 | The rest of these types correspond to existing Perl concepts. For |
61 | example, a C<Num> is anything that Perl thinks looks like a number. An |
62 | C<Object> is a blessed reference, etc. |
63 | |
64 | The types followed by "[`a]" can be parameterized. So instead of just |
65 | plain C<ArrayRef> we can say that we want C<ArrayRef[Int]> instead. We |
66 | can even do something like C<HashRef[ArrayRef[Str]]>. |
67 | |
68 | The C<Maybe[`a]> type deserves a special mention. Used by itself, it |
69 | doesn't really mean anything (and is equivalent to C<Item>). When it |
70 | is parameterized, it means that the value is either C<undef> or the |
71 | parameterized type. So C<Maybe[Int]> means an integer or C<undef> |
72 | |
73 | For more details on the type hierarchy, see |
74 | L<Moose::Util::TypeConstraints>. |
75 | |
76 | =head1 WHAT IS A TYPE? |
77 | |
78 | It's important to realize that types are not classes (or |
79 | packages). Types are just objects (L<Moose::Meta::TypeConstraint> |
80 | objects, to be exact) with a name. Moose maintains a global type |
81 | registry that lets it convert names like "Num" into the appropriuate |
82 | object. |
83 | |
84 | However, class names I<can be> type names. When you define a new class |
85 | using Moose, it defines an associated type name behind the scenes: |
86 | |
87 | package MyApp::User; |
88 | |
89 | use Moose; |
90 | |
91 | Now you can use C<'MyApp::User'> as a type name: |
92 | |
93 | has creator => ( |
94 | is => 'rw', |
95 | isa => 'MyApp::User', |
96 | ); |
97 | |
98 | However, for non-Moose classes there's no magic. You may have to |
99 | explicitly declare the class type. This is a bit muddled because Moose |
100 | assumes that any unknown type name passed as the C<isa> value for an |
101 | attribute is a class. So this works: |
102 | |
103 | has 'birth_date' => ( |
104 | is => 'rw', |
105 | isa => 'DateTime', |
106 | ); |
107 | |
108 | In general, when Moose is presented with an unknown name, it assumes |
109 | that the name is a class: |
110 | |
111 | subtype 'ModernDateTime' |
112 | => as 'DateTime' |
113 | => where { $_->year() >= 1980 } |
114 | => message { 'The date you provided is not modern enough' }; |
115 | |
116 | has 'valid_dates' => ( |
117 | is => 'ro', |
118 | isa => 'ArrayRef[DateTime]', |
119 | ); |
120 | |
121 | Moose will assume that "DateTime" is a class name and create a type |
122 | accordingly. |
123 | |
124 | =head1 SUBTYPES |
125 | |
126 | Moose uses subtypes in its built-in hierarchy. C<Int> is a child of |
127 | C<Num> for example. |
128 | |
129 | A subtype is defined in terms of a parent type and a constraint. Any |
130 | constraints defined by the parent(s) will be checked first, and then |
131 | the subtype's constraint is checked. A value must pass I<all> of these |
132 | checks to be valid for the subtype. |
133 | |
134 | Generally, a subtype takes the parent's constraint and makes it more |
135 | specific. |
136 | |
137 | A subtype can also define its own constraint failure message. This |
138 | lets you do things like have an error "The value you provided (20), |
139 | was not a valid rating, which must be a number from 1-10." This is |
140 | much friendlier than the default error, which just says that the value |
141 | failed a validation check for the type. |
142 | |
143 | Here's a simple (and useful) subtype example: |
144 | |
145 | subtype 'PositiveInt' |
146 | => as 'Int' |
147 | => where { $_ > 0 } |
148 | => message { "The number you provided, $_, was not a positive number" } |
149 | |
150 | Note that the sugar functions for working with types are all exported |
151 | by L<Moose::Util::TypeConstraints>. |
152 | |
153 | =head2 Creating a New Type (That Isn't a Subtype) |
154 | |
155 | You can also create new top-level types: |
156 | |
157 | type 'FourCharacters' => where { defined $_ && length $_ == 4 }; |
158 | |
159 | In practice, this example is pretty much the same as doing the same |
160 | thing as a subtype of C<Str>, except you have to check defined-ness |
161 | yourself. |
162 | |
163 | It's hard to find a case where you wouldn't want to subtype a very |
164 | broad type like C<Defined>, C<Ref> or C<Object>. |
165 | |
166 | In practice, defining a new top-level type is conceptually the same as |
167 | subtyping C<Item>. |
168 | |
169 | =head1 TYPE NAMES |
170 | |
171 | Type names are global throughout the current Perl |
172 | interpreter. Internally, Moose maps names to type objects via |
173 | L<Moose::Meta::TypeConstraint::Registry|registry> singleton. |
174 | |
175 | If you have multiple apps or libraries all using Moose in the same |
176 | process, you could have problems with collisions. We recommend that |
177 | you prefix names with some sort of namespace indicator to prevent |
178 | these sorts of collisions. |
179 | |
180 | For example, instead of calling a type "PositiveInt", call it |
181 | "MyApp.Type.PositiveInt". |
182 | |
183 | Type names are just strings, and can contain any character you |
184 | want. We recommend that you I<do not> use "::" as a separator in type |
185 | names. This can be very confusing, because class names are I<also> |
186 | valid type names! Using something else, like a period, makes it clear |
187 | that "MyApp::User" is a class and "MyApp.Type.PositiveInt" is a Moose |
188 | type defined by your application. |
189 | |
190 | The C<MooseX::Types> module lets you create bareword aliases to longer |
191 | names (really, the barewords are functions). |
192 | |
193 | =head1 COERCION |
194 | |
195 | One of the most powerful features of Moose's type system is its |
196 | coercions. A coercion is a mapping between two types. |
197 | |
198 | subtype 'ArrayRefOfInts' |
199 | => as 'ArrayRef[Int]'; |
200 | |
201 | coerce 'ArrayRefOfInts' |
202 | => from 'Int' |
203 | => via { [ $_ ] }; |
204 | |
205 | You'll note that we had to create a subtype rather than coercing |
206 | C<ArrayRef[Int]> directly. This is just a quirk of how Moose |
207 | works. |
208 | |
209 | Coercions, like type names, are global. This is I<another> reason why |
210 | it is good to namespace your types. Moose will I<never> try to coerce |
211 | a value unless you explicitly ask for it. This is done by setting the |
212 | C<coerce> attribute parameter to a true value: |
213 | |
214 | package Foo; |
215 | |
216 | has 'sizes' => ( |
217 | is => 'rw', |
218 | isa => 'ArrayRefOfInts', |
219 | coerce => 1, |
220 | ); |
221 | |
222 | Foo->new( sizes => 42 ); |
223 | |
224 | This code example will do the right thing, and the newly created |
225 | object will have C<[ 42 ]> as its C<sizes> attribute. |
226 | |
227 | =head2 Deep Coercion |
228 | |
229 | Deep coercion is the coercion of type parameters for parameterized |
230 | types. Let's take these types as an example: |
231 | |
232 | subtype 'HexNum' |
233 | => as 'Str' |
234 | => where { /[a-f0-9]/i }; |
235 | |
236 | coerce 'Int' |
237 | => from 'HexNum' |
238 | => via { hex $_ }; |
239 | |
240 | has 'sizes' => ( |
241 | is => 'rw', |
242 | isa => 'ArrayRef[Int]', |
243 | coerce => 1, |
244 | ); |
245 | |
246 | If we try passing an array reference of hex numbers for the C<sizes> |
247 | attribute, Moose will not do any coercion. The reason for this is that |
248 | it gets very complicate very fast. |
249 | |
250 | However, if you want to, you can define a set of subtypes to enable |
251 | coercion between two parameterized types. |
252 | |
253 | subtype 'ArrayRefOfHexNums' |
254 | => as 'ArrayRef[HexNum]'; |
255 | |
256 | subtype 'ArrayRefOfInts' |
257 | => as 'ArrayRef[Int]'; |
258 | |
259 | coerce 'ArrayRefOfInts' |
260 | => from 'ArrayRefOfHexNums' |
261 | => via { [ map { hex } @{$_} ] }; |
262 | |
263 | Foo->new( sizes => [ 'a1', 'ff', '22' ] ); |
264 | |
265 | Now Moose will coerce the hex numbers to integers. |
266 | |
267 | However, Moose does not attempt to chain coercions, so we cannot pass |
268 | a single hex number. If we want to make that possible as well, we need |
269 | to define yet another coercion: |
270 | |
271 | coerce 'ArrayRefOfInts' |
272 | => from 'HexNum' |
273 | => via { [ hex $_ ] }; |
274 | |
275 | Yes, this can all get verbose, but coercion is tricky magic, and we |
276 | think it's best to make it as explicit as possible. |
277 | |
278 | =head1 TYPE UNIONS |
279 | |
280 | Moose allows you to say that an attribute can be of two or more |
281 | disparate types. For example, we might allow an C<Object> or |
282 | C<FileHandle>: |
283 | |
284 | has 'output' => ( |
285 | is => 'rw', |
286 | isa => 'Object | FileHandle', |
287 | ); |
288 | |
289 | Moose actually parses that string and recognizes that you are creating |
290 | a type union. The C<output> attribute will accept any sort of object, |
291 | as well as an unblessed file handle. It is up to you to do the right |
292 | thing for each of them in your code. |
293 | |
294 | Whenever you consider using a type union, you should think about |
295 | whether or not coercion might be a better answer. |
296 | |
297 | For our example above, we might want to be more specific, and insist |
298 | that output be an object with a C<print> method: |
299 | |
300 | subtype 'CanPrint' |
301 | => as 'Object' |
302 | => where { $_->can('print') }; |
303 | |
304 | We can coerce file handles to an object that satisfies this condition |
305 | with a simple wrapper class: |
306 | |
307 | package FHWrapper; |
308 | |
309 | use Moose; |
310 | |
311 | has 'handle' => ( |
312 | is => 'ro', |
313 | isa => 'FileHandle', |
314 | ); |
315 | |
316 | sub print { |
317 | my $self = shift; |
318 | my $fh = $self->handle(); |
319 | |
320 | print $fh @_; |
321 | } |
322 | |
323 | Now we can define a coercion from C<FileHandle> to our wrapper class: |
324 | |
325 | coerce 'FHWrapper' |
326 | => from 'FileHandle' |
327 | => via { FHWrapper->new( handle => $_ ) }; |
328 | |
329 | has 'output' => ( |
330 | is => 'rw', |
331 | isa => 'CanPrint', |
332 | coerce => 1, |
333 | ); |
334 | |
335 | This pattern, using a coercion instead of a type union, can help |
336 | simplify the use of the attribute, and should be considered whenever |
337 | you have a type union. |
338 | |
339 | =head1 TYPE CREATION HELPERS |
340 | |
341 | The L<Moose::Util::TypeConstraints> module exports a number of helper |
342 | functions for creating specific kinds of types. These include |
343 | C<class_type>, C<role_type>, and C<maybe_type>. See the docs for |
344 | details. |
345 | |
346 | One helper worth noting is C<enum>, which allows you to create a |
347 | subtype of C<Str> that only allows the specified values: |
348 | |
349 | enum 'RGB' => qw( red green blue ); |
350 | |
351 | This creates a type named C<RGB> |
352 | |
353 | =head1 ANONYMOUS TYPES |
354 | |
355 | All of the type creation functions return a type object. This type |
356 | object can be used wherever you would use a type name, as a parent |
357 | type, or as the value for an attribute's C<isa> parameter: |
358 | |
359 | has 'size' => ( |
360 | is => 'rw', |
361 | isa => subtype 'Int' => where { $_ > 0 }, |
362 | ); |
363 | |
364 | This is handy when you want to create a one-off type and don't want to |
365 | "pollute" the global namespace registry. |
366 | |
367 | =head1 VALIDATING METHOD PARAMETERS |
368 | |
369 | Moose does not provide any means of validating method |
370 | parameters. However, there are several MooseX extensions on CPAN which |
371 | let you do this. |
372 | |
373 | The simplest and least sugary is C<MooseX::Params::Validate>. This |
374 | lets you validate a set of named parameters using Moose types: |
375 | |
376 | use Moose; |
377 | use MooseX::Params::Validate; |
378 | |
379 | sub foo { |
380 | my $self = shift; |
381 | my %params = validate( |
382 | \@_, |
383 | bar => { isa => 'Str', default => 'Moose' }, |
384 | ); |
385 | ... |
386 | } |
387 | |
388 | C<MooseX::Params::Validate> also supports coercions. |
389 | |
390 | There are several more powerful extensions that support method |
391 | parameter validation using Moose types, including |
392 | C<MooseX::Method::Signatures>, which gives you a full-blown C<method> |
393 | keyword. |
394 | |
395 | method morning (Str $name) { |
396 | $self->say("Good morning ${name}!"); |
397 | } |
398 | |
399 | =head1 AUTHOR |
400 | |
401 | Dave Rolsky E<lt>autarch@urth.orgE<gt> |
402 | |
403 | =head1 COPYRIGHT AND LICENSE |
404 | |
405 | Copyright 2008 by Infinity Interactive, Inc. |
406 | |
407 | L<http://www.iinteractive.com> |
408 | |
409 | This library is free software; you can redistribute it and/or modify |
410 | it under the same terms as Perl itself. |
411 | |
412 | =cut |