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