NAME

VERSION

version 2.1204

TYPES IN PERL?

Moose provides its own type system for attributes. You can also use these types to validate method parameters with the help of a MooseX module.

Moose's type system is based on a combination of Perl 5's own implicit types and some Perl 6 concepts. You can create your own subtypes with custom constraints, making it easy to express any sort of validation.

Types have names, and you can re-use them by name, making it easy to share types throughout a large application.

However, this is not a "real" type system. Moose does not magically make Perl start associating types with variables. This is just an advanced parameter checking system which allows you to associate a name with a constraint.

That said, it's still pretty damn useful, and we think it's one of the things that makes Moose both fun and powerful. Taking advantage of the type system makes it much easier to ensure that you are getting valid data, and it also contributes greatly to code maintainability.

The types followed by "[`a]" can be parameterized. So instead of just plain ArrayRef we can say that we want ArrayRef[Int] instead. We can even do something like HashRef[ArrayRef[Str]].

The Maybe[`a] type deserves a special mention. Used by itself, it doesn't really mean anything (and is equivalent to Item). When it is parameterized, it means that the value is either undef or the parameterized type. So Maybe[Int] means an integer or undef.

WHAT IS A TYPE?

It's important to realize that types are not classes (or packages). Types are just objects (Moose::Meta::TypeConstraint objects, to be exact) with a name and a constraint. Moose maintains a global type registry that lets it convert names like Num into the appropriate object.

However, class names can be type names. When you define a new class using Moose, it defines an associated type name behind the scenes:

package MyApp::User;
use Moose;

Now you can use 'MyApp::User' as a type name:

has creator => (
is => 'ro',
isa => 'MyApp::User',
);

However, for non-Moose classes there's no magic. You may have to explicitly declare the class type. This is a bit muddled because Moose assumes that any unknown type name passed as the isa value for an attribute is a class. So this works:

has 'birth_date' => (
is => 'ro',
isa => 'DateTime',
);

In general, when Moose is presented with an unknown name, it assumes that the name is a class:

Moose will assume that DateTime is a class name in both of these instances.

SUBTYPES

Moose uses subtypes in its built-in hierarchy. For example, Int is a child of Num.

A subtype is defined in terms of a parent type and a constraint. Any constraints defined by the parent(s) will be checked first, followed by constraints defined by the subtype. A value must pass all of these checks to be valid for the subtype.

Typically, a subtype takes the parent's constraint and makes it more specific.

A subtype can also define its own constraint failure message. This lets you do things like have an error "The value you provided (20), was not a valid rating, which must be a number from 1-10." This is much friendlier than the default error, which just says that the value failed a validation check for the type. The default error can, however, be made more friendly by installing Devel::PartialDump (version 0.14 or higher), which Moose will use if possible to display the invalid value.

Here's a simple (and useful) subtype example:

subtype 'PositiveInt',
as 'Int',
where { $_ > 0 },
message { "The number you provided, $_, was not a positive number" };

TYPE NAMES

Type names are global throughout the current Perl interpreter. Internally, Moose maps names to type objects via a registry.

If you have multiple apps or libraries all using Moose in the same process, you could have problems with collisions. We recommend that you prefix names with some sort of namespace indicator to prevent these sorts of collisions.

For example, instead of calling a type "PositiveInt", call it "MyApp::Type::PositiveInt" or "MyApp::Types::PositiveInt". We recommend that you centralize all of these definitions in a single package, MyApp::Types, which can be loaded by other classes in your application.

However, before you do this, you should look at the MooseX::Types module. This module makes it easy to create a "type library" module, which can export your types as perl constants.

has 'counter' => (is => 'rw', isa => PositiveInt);

This lets you use a short name rather than needing to fully qualify the name everywhere. It also allows you to easily create parameterized types:

has 'counts' => (is => 'ro', isa => HashRef[PositiveInt]);

This module will check your names at compile time, and is generally more robust than the string type parsing for complex cases.

COERCION

A coercion lets you tell Moose to automatically convert one type to another.

Moose does not attempt to chain coercions, so it will not coerce a single hex number. To do that, we need to define a separate coercion:

coerce 'ArrayRefOfInts',
from 'HexNum',
via { [ hex $_ ] };

Yes, this can all get verbose, but coercion is tricky magic, and we think it's best to make it explicit.

TYPE UNIONS

Moose allows you to say that an attribute can be of two or more disparate types. For example, we might allow an Object or FileHandle:

has 'output' => (
is => 'rw',
isa => 'Object | FileHandle',
);

Moose actually parses that string and recognizes that you are creating a type union. The output attribute will accept any sort of object, as well as an unblessed file handle. It is up to you to do the right thing for each of them in your code.

Whenever you use a type union, you should consider whether or not coercion might be a better answer.

For our example above, we might want to be more specific, and insist that output be an object with a print method:

duck_type 'CanPrint', [qw(print)];

We can coerce file handles to an object that satisfies this condition with a simple wrapper class:

This pattern of using a coercion instead of a type union will help make your class internals simpler.

TYPE CREATION HELPERS

The Moose::Util::TypeConstraints module exports a number of helper functions for creating specific kinds of types. These include class_type, role_type, maybe_type, and duck_type. See the docs for details.

One helper worth noting is enum, which allows you to create a subtype of Str that only allows the specified values:

enum 'RGB', [qw( red green blue )];

This creates a type named RGB.

ANONYMOUS TYPES

All of the type creation functions return a type object. This type object can be used wherever you would use a type name, as a parent type, or as the value for an attribute's isa option: