This commit is contained in:
709
CPAN/Moose/Manual/Attributes.pod
Normal file
709
CPAN/Moose/Manual/Attributes.pod
Normal file
@@ -0,0 +1,709 @@
|
||||
# PODNAME: Moose::Manual::Attributes
|
||||
# ABSTRACT: Object attributes with Moose
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Moose::Manual::Attributes - Object attributes with Moose
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 2.2207
|
||||
|
||||
=head1 INTRODUCTION
|
||||
|
||||
Moose attributes have many properties, and attributes are probably the
|
||||
single most powerful and flexible part of Moose. You can create a
|
||||
powerful class simply by declaring attributes. In fact, it's possible
|
||||
to have classes that consist solely of attribute declarations.
|
||||
|
||||
An attribute is a property that every member of a class has. For
|
||||
example, we might say that "every C<Person> object has a first name and
|
||||
last name". Attributes can be optional, so that we can say "some C<Person>
|
||||
objects have a social security number (and some don't)".
|
||||
|
||||
At its simplest, an attribute can be thought of as a named value (as
|
||||
in a hash) that can be read and set. However, attributes can also have
|
||||
defaults, type constraints, delegation and much more.
|
||||
|
||||
In other languages, attributes are also referred to as slots or
|
||||
properties.
|
||||
|
||||
=head1 ATTRIBUTE OPTIONS
|
||||
|
||||
Use the C<has> function to declare an attribute:
|
||||
|
||||
package Person;
|
||||
|
||||
use Moose;
|
||||
|
||||
has 'first_name' => ( is => 'rw' );
|
||||
|
||||
This says that all C<Person> objects have an optional read-write
|
||||
"first_name" attribute.
|
||||
|
||||
=head2 Read-write vs. read-only
|
||||
|
||||
The options passed to C<has> define the properties of the attribute. There are
|
||||
many options, but in the simplest form you just need to set C<is>, which can
|
||||
be either C<ro> (read-only) or C<rw> (read-write). When an attribute is C<rw>,
|
||||
you can change it by passing a value to its accessor. When an attribute is
|
||||
C<ro>, you may only read the current value of the attribute through its
|
||||
accessor. You can, however, set the attribute when creating the object by
|
||||
passing it to the constructor.
|
||||
|
||||
In fact, you could even omit C<is>, but that gives you an attribute
|
||||
that has no accessor. This can be useful with other attribute options,
|
||||
such as C<handles>. However, if your attribute generates I<no>
|
||||
accessors, Moose will issue a warning, because that usually means the
|
||||
programmer forgot to say the attribute is read-only or read-write. If
|
||||
you really mean to have no accessors, you can silence this warning by
|
||||
setting C<is> to C<bare>.
|
||||
|
||||
=head2 Accessor methods
|
||||
|
||||
Each attribute has one or more accessor methods. An accessor lets you
|
||||
read and write the value of that attribute for an object.
|
||||
|
||||
By default, the accessor method has the same name as the attribute. If
|
||||
you declared your attribute as C<ro> then your accessor will be
|
||||
read-only. If you declared it as C<rw>, you get a read-write
|
||||
accessor. Simple.
|
||||
|
||||
Given our C<Person> example above, we now have a single C<first_name>
|
||||
accessor that can read or write a C<Person> object's C<first_name>
|
||||
attribute's value.
|
||||
|
||||
If you want, you can also explicitly specify the method names to be
|
||||
used for reading and writing an attribute's value. This is
|
||||
particularly handy when you'd like an attribute to be publicly
|
||||
readable, but only privately settable. For example:
|
||||
|
||||
has 'weight' => (
|
||||
is => 'ro',
|
||||
writer => '_set_weight',
|
||||
);
|
||||
|
||||
This might be useful if weight is calculated based on other methods.
|
||||
For example, every time the C<eat> method is called, we might adjust
|
||||
weight. This lets us hide the implementation details of weight
|
||||
changes, but still provide the weight value to users of the class.
|
||||
|
||||
Some people might prefer to have distinct methods for reading and
|
||||
writing. In I<Perl Best Practices>, Damian Conway recommends that
|
||||
reader methods start with "get_" and writer methods start with "set_".
|
||||
|
||||
We can do exactly that by providing names for both the C<reader> and
|
||||
C<writer> methods:
|
||||
|
||||
has 'weight' => (
|
||||
is => 'rw',
|
||||
reader => 'get_weight',
|
||||
writer => 'set_weight',
|
||||
);
|
||||
|
||||
If you're thinking that doing this over and over would be insanely
|
||||
tedious, you're right! Fortunately, Moose provides a powerful
|
||||
extension system that lets you override the default naming
|
||||
conventions. See L<Moose::Manual::MooseX> for more details.
|
||||
|
||||
=head2 Predicate and clearer methods
|
||||
|
||||
Moose allows you to explicitly distinguish between a false or
|
||||
undefined attribute value and an attribute which has not been set. If
|
||||
you want to access this information, you must define clearer and
|
||||
predicate methods for an attribute.
|
||||
|
||||
A predicate method tells you whether or not a given attribute is
|
||||
currently set. Note that an attribute can be explicitly set to
|
||||
C<undef> or some other false value, but the predicate will return
|
||||
true.
|
||||
|
||||
The clearer method unsets the attribute. This is I<not> the
|
||||
same as setting the value to C<undef>, but you can only distinguish
|
||||
between them if you define a predicate method!
|
||||
|
||||
Here's some code to illustrate the relationship between an accessor,
|
||||
predicate, and clearer method.
|
||||
|
||||
package Person;
|
||||
|
||||
use Moose;
|
||||
|
||||
has 'ssn' => (
|
||||
is => 'rw',
|
||||
clearer => 'clear_ssn',
|
||||
predicate => 'has_ssn',
|
||||
);
|
||||
|
||||
...
|
||||
|
||||
my $person = Person->new();
|
||||
$person->has_ssn; # false
|
||||
|
||||
$person->ssn(undef);
|
||||
$person->ssn; # returns undef
|
||||
$person->has_ssn; # true
|
||||
|
||||
$person->clear_ssn;
|
||||
$person->ssn; # returns undef
|
||||
$person->has_ssn; # false
|
||||
|
||||
$person->ssn('123-45-6789');
|
||||
$person->ssn; # returns '123-45-6789'
|
||||
$person->has_ssn; # true
|
||||
|
||||
my $person2 = Person->new( ssn => '111-22-3333');
|
||||
$person2->has_ssn; # true
|
||||
|
||||
By default, Moose does not make a predicate or clearer for you. You must
|
||||
explicitly provide names for them, and then Moose will create the methods
|
||||
for you.
|
||||
|
||||
=head2 Required or not?
|
||||
|
||||
By default, all attributes are optional, and do not need to be
|
||||
provided at object construction time. If you want to make an attribute
|
||||
required, simply set the C<required> option to true:
|
||||
|
||||
has 'name' => (
|
||||
is => 'ro',
|
||||
required => 1,
|
||||
);
|
||||
|
||||
There are a couple caveats worth mentioning in regards to what
|
||||
"required" actually means.
|
||||
|
||||
Basically, all it says is that this attribute (C<name>) must be provided to
|
||||
the constructor or it must have either a default or a builder. It does not say
|
||||
anything about its value, so it could be C<undef>.
|
||||
|
||||
If you define a clearer method on a required attribute, the clearer
|
||||
I<will> work, so even a required attribute can be unset after object
|
||||
construction.
|
||||
|
||||
This means that if you do make an attribute required, providing a
|
||||
clearer doesn't make much sense. In some cases, it might be handy to
|
||||
have a I<private> C<clearer> and C<predicate> for a required
|
||||
attribute.
|
||||
|
||||
=head2 Default and builder methods
|
||||
|
||||
Attributes can have default values, and Moose provides two ways to
|
||||
specify that default.
|
||||
|
||||
In the simplest form, you simply provide a non-reference scalar value
|
||||
for the C<default> option:
|
||||
|
||||
has 'size' => (
|
||||
is => 'ro',
|
||||
default => 'medium',
|
||||
predicate => 'has_size',
|
||||
);
|
||||
|
||||
If the size attribute is not provided to the constructor, then it ends
|
||||
up being set to C<medium>:
|
||||
|
||||
my $person = Person->new();
|
||||
$person->size; # medium
|
||||
$person->has_size; # true
|
||||
|
||||
You can also provide a subroutine reference for C<default>. This
|
||||
reference will be called as a method on the object.
|
||||
|
||||
has 'size' => (
|
||||
is => 'ro',
|
||||
default =>
|
||||
sub { ( 'small', 'medium', 'large' )[ int( rand 3 ) ] },
|
||||
predicate => 'has_size',
|
||||
);
|
||||
|
||||
This is a trivial example, but it illustrates the point that the subroutine
|
||||
will be called for every new object created.
|
||||
|
||||
When you provide a C<default> subroutine reference, it is called as a
|
||||
method on the object, with no additional parameters:
|
||||
|
||||
has 'size' => (
|
||||
is => 'ro',
|
||||
default => sub {
|
||||
my $self = shift;
|
||||
|
||||
return $self->height > 200 ? 'large' : 'average';
|
||||
},
|
||||
);
|
||||
|
||||
When the C<default> is called during object construction, it may be
|
||||
called before other attributes have been set. If your default is
|
||||
dependent on other parts of the object's state, you can make the
|
||||
attribute C<lazy>. Laziness is covered in the next section.
|
||||
|
||||
If you want to use a reference of any sort as the default value, you
|
||||
must return it from a subroutine.
|
||||
|
||||
has 'mapping' => (
|
||||
is => 'ro',
|
||||
default => sub { {} },
|
||||
);
|
||||
|
||||
This is necessary because otherwise Perl would instantiate the reference
|
||||
exactly once, and it would be shared by all objects:
|
||||
|
||||
has 'mapping' => (
|
||||
is => 'ro',
|
||||
default => {}, # wrong!
|
||||
);
|
||||
|
||||
Moose will throw an error if you pass a bare non-subroutine reference
|
||||
as the default.
|
||||
|
||||
If Moose allowed this then the default mapping attribute could easily
|
||||
end up shared across many objects. Instead, wrap it in a subroutine
|
||||
reference as we saw above.
|
||||
|
||||
This is a bit awkward, but it's just the way Perl works.
|
||||
|
||||
As an alternative to using a subroutine reference, you can supply a C<builder>
|
||||
method for your attribute:
|
||||
|
||||
has 'size' => (
|
||||
is => 'ro',
|
||||
builder => '_build_size',
|
||||
predicate => 'has_size',
|
||||
);
|
||||
|
||||
sub _build_size {
|
||||
return ( 'small', 'medium', 'large' )[ int( rand 3 ) ];
|
||||
}
|
||||
|
||||
This has several advantages. First, it moves a chunk of code to its own named
|
||||
method, which improves readability and code organization. Second, because this
|
||||
is a I<named> method, it can be subclassed or provided by a role.
|
||||
|
||||
We strongly recommend that you use a C<builder> instead of a
|
||||
C<default> for anything beyond the most trivial default.
|
||||
|
||||
A C<builder>, just like a C<default>, is called as a method on the
|
||||
object with no additional parameters.
|
||||
|
||||
=head3 Builders allow subclassing
|
||||
|
||||
Because the C<builder> is called I<by name>, it goes through Perl's
|
||||
method resolution. This means that builder methods are both
|
||||
inheritable and overridable.
|
||||
|
||||
If we subclass our C<Person> class, we can override C<_build_size>:
|
||||
|
||||
package Lilliputian;
|
||||
|
||||
use Moose;
|
||||
extends 'Person';
|
||||
|
||||
sub _build_size { return 'small' }
|
||||
|
||||
=head3 Builders work well with roles
|
||||
|
||||
Because builders are called by name, they work well with roles. For
|
||||
example, a role could provide an attribute but require that the
|
||||
consuming class provide the C<builder>:
|
||||
|
||||
package HasSize;
|
||||
use Moose::Role;
|
||||
|
||||
requires '_build_size';
|
||||
|
||||
has 'size' => (
|
||||
is => 'ro',
|
||||
lazy => 1,
|
||||
builder => '_build_size',
|
||||
);
|
||||
|
||||
package Lilliputian;
|
||||
use Moose;
|
||||
|
||||
with 'HasSize';
|
||||
|
||||
sub _build_size { return 'small' }
|
||||
|
||||
Roles are covered in L<Moose::Manual::Roles>.
|
||||
|
||||
=head2 Laziness
|
||||
|
||||
Moose lets you defer attribute population by making an attribute
|
||||
C<lazy>:
|
||||
|
||||
has 'size' => (
|
||||
is => 'ro',
|
||||
lazy => 1,
|
||||
builder => '_build_size',
|
||||
);
|
||||
|
||||
When C<lazy> is true, the default is not generated until the reader
|
||||
method is called, rather than at object construction time. There are
|
||||
several reasons you might choose to do this.
|
||||
|
||||
First, if the default value for this attribute depends on some other
|
||||
attributes, then the attribute I<must> be C<lazy>. During object
|
||||
construction, defaults are not generated in a predictable order, so
|
||||
you cannot count on some other attribute being populated when
|
||||
generating a default.
|
||||
|
||||
Second, there's often no reason to calculate a default before it's
|
||||
needed. Making an attribute C<lazy> lets you defer the cost until the
|
||||
attribute is needed. If the attribute is I<never> needed, you save
|
||||
some CPU time.
|
||||
|
||||
We recommend that you make any attribute with a builder or non-trivial
|
||||
default C<lazy> as a matter of course.
|
||||
|
||||
=head3 Lazy defaults and C<$_>
|
||||
|
||||
Please note that a lazy default or builder can be called anywhere, even inside
|
||||
a C<map> or C<grep>. This means that if your default sub or builder changes
|
||||
C<$_>, something weird could happen. You can prevent this by adding C<local
|
||||
$_> inside your default or builder.
|
||||
|
||||
=head2 Constructor parameters (C<init_arg>)
|
||||
|
||||
By default, each attribute can be passed by name to the class's
|
||||
constructor. On occasion, you may want to use a different name for
|
||||
the constructor parameter. You may also want to make an attribute
|
||||
unsettable via the constructor.
|
||||
|
||||
You can do either of these things with the C<init_arg> option:
|
||||
|
||||
has 'bigness' => (
|
||||
is => 'ro',
|
||||
init_arg => 'size',
|
||||
);
|
||||
|
||||
Now we have an attribute named "bigness", but we pass C<size> to the
|
||||
constructor.
|
||||
|
||||
Even more useful is the ability to disable setting an attribute via
|
||||
the constructor. This is particularly handy for private attributes:
|
||||
|
||||
has '_genetic_code' => (
|
||||
is => 'ro',
|
||||
lazy => 1,
|
||||
builder => '_build_genetic_code',
|
||||
init_arg => undef,
|
||||
);
|
||||
|
||||
By setting the C<init_arg> to C<undef>, we make it impossible to set
|
||||
this attribute when creating a new object.
|
||||
|
||||
=head2 Weak references
|
||||
|
||||
Moose has built-in support for weak references. If you set the
|
||||
C<weak_ref> option to a true value, then it will call
|
||||
C<Scalar::Util::weaken> whenever the attribute is set:
|
||||
|
||||
has 'parent' => (
|
||||
is => 'rw',
|
||||
weak_ref => 1,
|
||||
);
|
||||
|
||||
$node->parent($parent_node);
|
||||
|
||||
This is very useful when you're building objects that may contain
|
||||
circular references.
|
||||
|
||||
When the object in a weak reference goes out of scope, the attribute's value
|
||||
will become C<undef> "behind the scenes". This is done by the Perl interpreter
|
||||
directly, so Moose does not see this change. This means that triggers don't
|
||||
fire, coercions aren't applied, etc.
|
||||
|
||||
The attribute is not cleared, so a predicate method for that attribute will
|
||||
still return true. Similarly, when the attribute is next accessed, a default
|
||||
value will not be generated.
|
||||
|
||||
=head2 Triggers
|
||||
|
||||
A C<trigger> is a subroutine that is called whenever the attribute is
|
||||
set:
|
||||
|
||||
has 'size' => (
|
||||
is => 'rw',
|
||||
trigger => \&_size_set,
|
||||
);
|
||||
|
||||
sub _size_set {
|
||||
my ( $self, $size, $old_size ) = @_;
|
||||
|
||||
my $msg = $self->name;
|
||||
|
||||
if ( @_ > 2 ) {
|
||||
$msg .= " - old size was $old_size";
|
||||
}
|
||||
|
||||
$msg .= " - size is now $size";
|
||||
warn $msg;
|
||||
}
|
||||
|
||||
The trigger is called I<after> an attribute's value is set. It is
|
||||
called as a method on the object, and receives the new and old values as
|
||||
its arguments. If the attribute had not previously been set at all,
|
||||
then only the new value is passed. This lets you distinguish between
|
||||
the case where the attribute had no value versus when the old value was C<undef>.
|
||||
|
||||
This differs from an C<after> method modifier in two ways. First, a
|
||||
trigger is only called when the attribute is set, as opposed to
|
||||
whenever the accessor method is called (for reading or
|
||||
writing). Second, it is also called when an attribute's value is
|
||||
passed to the constructor.
|
||||
|
||||
However, triggers are I<not> called when an attribute is populated
|
||||
from a C<default> or C<builder>.
|
||||
|
||||
=head2 Attribute types
|
||||
|
||||
Attributes can be restricted to only accept certain types:
|
||||
|
||||
has 'first_name' => (
|
||||
is => 'ro',
|
||||
isa => 'Str',
|
||||
);
|
||||
|
||||
This says that the C<first_name> attribute must be a string.
|
||||
|
||||
Moose also provides a shortcut for specifying that an attribute only
|
||||
accepts objects that do a certain role:
|
||||
|
||||
has 'weapon' => (
|
||||
is => 'rw',
|
||||
does => 'MyApp::Weapon',
|
||||
);
|
||||
|
||||
See the L<Moose::Manual::Types> documentation for a complete
|
||||
discussion of Moose's type system.
|
||||
|
||||
=head2 Delegation
|
||||
|
||||
An attribute can define methods which simply delegate to its value:
|
||||
|
||||
has 'hair_color' => (
|
||||
is => 'ro',
|
||||
isa => 'Graphics::Color::RGB',
|
||||
handles => { hair_color_hex => 'as_hex_string' },
|
||||
);
|
||||
|
||||
This adds a new method, C<hair_color_hex>. When someone calls
|
||||
C<hair_color_hex>, internally, the object just calls C<<
|
||||
$self->hair_color->as_hex_string >>.
|
||||
|
||||
See L<Moose::Manual::Delegation> for documentation on how to set up
|
||||
delegation methods.
|
||||
|
||||
=head2 Attribute traits and metaclasses
|
||||
|
||||
One of Moose's best features is that it can be extended in all sorts of ways
|
||||
through the use of metaclass traits and custom metaclasses.
|
||||
|
||||
You can apply one or more traits to an attribute:
|
||||
|
||||
use MooseX::MetaDescription;
|
||||
|
||||
has 'size' => (
|
||||
is => 'ro',
|
||||
traits => ['MooseX::MetaDescription::Meta::Trait'],
|
||||
description => {
|
||||
html_widget => 'text_input',
|
||||
serialize_as => 'element',
|
||||
},
|
||||
);
|
||||
|
||||
The advantage of traits is that you can mix more than one of them
|
||||
together easily (in fact, a trait is just a role under the hood).
|
||||
|
||||
There are a number of MooseX modules on CPAN which provide useful
|
||||
attribute metaclasses and traits. See L<Moose::Manual::MooseX> for
|
||||
some examples. You can also write your own metaclasses and traits. See
|
||||
the "Meta" and "Extending" recipes in L<Moose::Cookbook> for examples.
|
||||
|
||||
=head2 Native Delegations
|
||||
|
||||
Native delegations allow you to delegate to standard Perl data structures as
|
||||
if they were objects.
|
||||
|
||||
For example, we can pretend that an array reference has methods like
|
||||
C<push()>, C<shift()>, C<map()>, C<count()>, and more.
|
||||
|
||||
has 'options' => (
|
||||
traits => ['Array'],
|
||||
is => 'ro',
|
||||
isa => 'ArrayRef[Str]',
|
||||
default => sub { [] },
|
||||
handles => {
|
||||
all_options => 'elements',
|
||||
add_option => 'push',
|
||||
map_options => 'map',
|
||||
option_count => 'count',
|
||||
sorted_options => 'sort',
|
||||
},
|
||||
);
|
||||
|
||||
See L<Moose::Manual::Delegation> for more details.
|
||||
|
||||
=head1 ATTRIBUTE INHERITANCE
|
||||
|
||||
By default, a child inherits all of its parent class(es)' attributes
|
||||
as-is. However, you can change most aspects of the inherited attribute in the
|
||||
child class. You cannot change any of its associated method names (reader,
|
||||
writer, predicate, etc).
|
||||
|
||||
To change some aspects of an attribute, you simply prepend a plus sign (C<+>)
|
||||
to its name:
|
||||
|
||||
package LazyPerson;
|
||||
|
||||
use Moose;
|
||||
|
||||
extends 'Person';
|
||||
|
||||
has '+first_name' => (
|
||||
lazy => 1,
|
||||
default => 'Bill',
|
||||
);
|
||||
|
||||
Now the C<first_name> attribute in C<LazyPerson> is lazy, and defaults
|
||||
to C<'Bill'>.
|
||||
|
||||
We recommend that you exercise caution when changing the type (C<isa>)
|
||||
of an inherited attribute.
|
||||
|
||||
=head2 Attribute Inheritance and Method Modifiers
|
||||
|
||||
When an inherited attribute is defined, that creates an entirely new set of
|
||||
accessors for the attribute (reader, writer, predicate, etc.). This is
|
||||
necessary because these may be what was changed when inheriting the attribute.
|
||||
|
||||
As a consequence, any method modifiers defined on the attribute's accessors in
|
||||
an ancestor class will effectively be ignored, because the new accessors live
|
||||
in the child class and do not see the modifiers from the parent class.
|
||||
|
||||
=head1 MULTIPLE ATTRIBUTE SHORTCUTS
|
||||
|
||||
If you have a number of attributes that differ only by name, you can declare
|
||||
them all at once:
|
||||
|
||||
package Point;
|
||||
|
||||
use Moose;
|
||||
|
||||
has [ 'x', 'y' ] => ( is => 'ro', isa => 'Int' );
|
||||
|
||||
Also, because C<has> is just a function call, you can call it in a loop:
|
||||
|
||||
for my $name ( qw( x y ) ) {
|
||||
my $builder = '_build_' . $name;
|
||||
has $name => ( is => 'ro', isa => 'Int', builder => $builder );
|
||||
}
|
||||
|
||||
=head1 MORE ON ATTRIBUTES
|
||||
|
||||
Moose attributes are a big topic, and this document glosses over a few
|
||||
aspects. We recommend that you read the L<Moose::Manual::Delegation>
|
||||
and L<Moose::Manual::Types> documents to get a more complete
|
||||
understanding of attribute features.
|
||||
|
||||
=head1 A FEW MORE OPTIONS
|
||||
|
||||
Moose has lots of attribute options. The ones listed below are
|
||||
superseded by some more modern features, but are covered for the sake
|
||||
of completeness.
|
||||
|
||||
=head2 The C<documentation> option
|
||||
|
||||
You can provide a piece of documentation as a string for an attribute:
|
||||
|
||||
has 'first_name' => (
|
||||
is => 'rw',
|
||||
documentation => q{The person's first (personal) name},
|
||||
);
|
||||
|
||||
Moose does absolutely nothing with this information other than store
|
||||
it.
|
||||
|
||||
=head2 The C<auto_deref> option
|
||||
|
||||
If your attribute is an array reference or hash reference, the
|
||||
C<auto_deref> option will make Moose dereference the value when it is
|
||||
returned from the reader method I<in list context>:
|
||||
|
||||
my %map = $object->mapping;
|
||||
|
||||
This option only works if your attribute is explicitly typed as an
|
||||
C<ArrayRef> or C<HashRef>. When the reader is called in I<scalar> context,
|
||||
the reference itself is returned.
|
||||
|
||||
However, we recommend that you use L<Moose::Meta::Attribute::Native> traits
|
||||
for these types of attributes, which gives you much more control over how
|
||||
they are accessed and manipulated. See also
|
||||
L<Moose::Manual::BestPractices#Use_Moose::Meta::Attribute::Native_traits_instead_of_auto_deref>.
|
||||
|
||||
=head2 Initializer
|
||||
|
||||
Moose provides an attribute option called C<initializer>. This is called when
|
||||
the attribute's value is being set in the constructor, and lets you change the
|
||||
value before it is set.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
Stevan Little <stevan@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=item *
|
||||
|
||||
Jesse Luehrs <doy@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Shawn M Moore <sartak@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
|
||||
|
||||
=item *
|
||||
|
||||
Karen Etheridge <ether@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Florian Ragwitz <rafl@debian.org>
|
||||
|
||||
=item *
|
||||
|
||||
Hans Dieter Pearcey <hdp@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Chris Prather <chris@prather.org>
|
||||
|
||||
=item *
|
||||
|
||||
Matt S Trout <mstrout@cpan.org>
|
||||
|
||||
=back
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2006 by Infinity Interactive, Inc.
|
||||
|
||||
This is free software; you can redistribute it and/or modify it under
|
||||
the same terms as the Perl 5 programming language system itself.
|
||||
|
||||
=cut
|
||||
292
CPAN/Moose/Manual/BestPractices.pod
Normal file
292
CPAN/Moose/Manual/BestPractices.pod
Normal file
@@ -0,0 +1,292 @@
|
||||
# PODNAME: Moose::Manual::BestPractices
|
||||
# ABSTRACT: Get the most out of Moose
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Moose::Manual::BestPractices - Get the most out of Moose
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 2.2207
|
||||
|
||||
=head1 RECOMMENDATIONS
|
||||
|
||||
Moose has a lot of features, and there's definitely more than one way
|
||||
to do it. However, we think that picking a subset of these features
|
||||
and using them consistently makes everyone's life easier.
|
||||
|
||||
Of course, as with any list of "best practices", these are really just
|
||||
opinions. Feel free to ignore us.
|
||||
|
||||
=head2 C<namespace::autoclean> and immutabilize
|
||||
|
||||
We recommend that you remove the Moose sugar and end your Moose class
|
||||
definitions by making your class immutable.
|
||||
|
||||
package Person;
|
||||
|
||||
use Moose;
|
||||
use namespace::autoclean;
|
||||
|
||||
# extends, roles, attributes, etc.
|
||||
|
||||
# methods
|
||||
|
||||
__PACKAGE__->meta->make_immutable;
|
||||
|
||||
1;
|
||||
|
||||
The C<use namespace::autoclean> bit is simply good code hygiene, as it removes
|
||||
imported symbols from your class's namespace at the end of your package's
|
||||
compile cycle, including Moose keywords. Once the class has been built, these
|
||||
keywords are not needed. (This is preferred to placing C<no Moose> at the end
|
||||
of your package).
|
||||
|
||||
The C<make_immutable> call allows Moose to speed up a lot of things, most
|
||||
notably object construction. The trade-off is that you can no longer change
|
||||
the class definition.
|
||||
|
||||
=head2 Never override C<new>
|
||||
|
||||
Overriding C<new> is a very bad practice. Instead, you should use a
|
||||
C<BUILD> or C<BUILDARGS> methods to do the same thing. When you
|
||||
override C<new>, Moose can no longer inline a constructor when your
|
||||
class is immutabilized.
|
||||
|
||||
There are two good reasons to override C<new>. One, you are writing a
|
||||
MooseX extension that provides its own L<Moose::Object> subclass
|
||||
I<and> a subclass of L<Moose::Meta::Method::Constructor> to inline the
|
||||
constructor. Two, you are subclassing a non-Moose parent.
|
||||
|
||||
If you know how to do that, you know when to ignore this best practice
|
||||
;)
|
||||
|
||||
=head2 Always call the original/parent C<BUILDARGS>
|
||||
|
||||
If you C<override> the C<BUILDARGS> method in your class, make sure to play
|
||||
nice and call C<super()> to handle cases you're not checking for explicitly.
|
||||
|
||||
The default C<BUILDARGS> method in L<Moose::Object> handles both a
|
||||
list and hashref of named parameters correctly, and also checks for a
|
||||
I<non-hashref> single argument.
|
||||
|
||||
=head2 Provide defaults whenever possible, otherwise use C<required>
|
||||
|
||||
When your class provides defaults, this makes constructing new objects
|
||||
simpler. If you cannot provide a default, consider making the
|
||||
attribute C<required>.
|
||||
|
||||
If you don't do either, an attribute can simply be left unset,
|
||||
increasing the complexity of your object, because it has more possible
|
||||
states that you or the user of your class must account for.
|
||||
|
||||
=head2 Use C<builder> instead of C<default> most of the time
|
||||
|
||||
Builders can be inherited, they have explicit names, and they're just
|
||||
plain cleaner.
|
||||
|
||||
However, I<do> use a default when the default is a non-reference,
|
||||
I<or> when the default is simply an empty reference of some sort.
|
||||
|
||||
Also, keep your builder methods private.
|
||||
|
||||
=head2 Be C<lazy>
|
||||
|
||||
Lazy is good, and often solves initialization ordering problems. It's also
|
||||
good for deferring work that may never have to be done. Make your attributes
|
||||
C<lazy> unless they're C<required> or have trivial defaults.
|
||||
|
||||
=head2 Consider keeping clearers and predicates private
|
||||
|
||||
Does everyone I<really> need to be able to clear an attribute?
|
||||
Probably not. Don't expose this functionality outside your class
|
||||
by default.
|
||||
|
||||
Predicates are less problematic, but there's no reason to make your
|
||||
public API bigger than it has to be.
|
||||
|
||||
=head2 Avoid C<lazy_build>
|
||||
|
||||
As described above, you rarely actually need a clearer or a predicate.
|
||||
C<lazy_build> adds both to your public API, which exposes you to use cases that
|
||||
you must now test for. It's much better to avoid adding them until you really
|
||||
need them - use explicit C<lazy> and C<builder> options instead.
|
||||
|
||||
=head2 Default to read-only, and consider keeping writers private
|
||||
|
||||
Making attributes mutable just means more complexity to account for in
|
||||
your program. The alternative to mutable state is to encourage users
|
||||
of your class to simply make new objects as needed.
|
||||
|
||||
If you I<must> make an attribute read-write, consider making the
|
||||
writer a separate private method. Narrower APIs are easy to maintain,
|
||||
and mutable state is trouble.
|
||||
|
||||
In order to declare such attributes, provide a private C<writer>
|
||||
parameter:
|
||||
|
||||
has pizza => (
|
||||
is => 'ro',
|
||||
isa => 'Pizza',
|
||||
writer => '_pizza',
|
||||
);
|
||||
|
||||
=head2 Think twice before changing an attribute's type in a subclass
|
||||
|
||||
Down this path lies great confusion. If the attribute is an object
|
||||
itself, at least make sure that it has the same interface as the type
|
||||
of object in the parent class.
|
||||
|
||||
=head2 Don't use the C<initializer> feature
|
||||
|
||||
Don't know what we're talking about? That's fine.
|
||||
|
||||
=head2 Use L<Moose::Meta::Attribute::Native> traits instead of C<auto_deref>
|
||||
|
||||
The C<auto_deref> feature is a bit troublesome. Directly exposing a complex
|
||||
attribute is ugly. Instead, consider using L<Moose::Meta::Attribute::Native>
|
||||
traits to define an API that only exposes the necessary pieces of
|
||||
functionality.
|
||||
|
||||
=head2 Always call C<inner> in the most specific subclass
|
||||
|
||||
When using C<augment> and C<inner>, we recommend that you call
|
||||
C<inner> in the most specific subclass of your hierarchy. This makes
|
||||
it possible to subclass further and extend the hierarchy without
|
||||
changing the parents.
|
||||
|
||||
=head2 Namespace your types
|
||||
|
||||
Use some sort of namespacing convention for type names. We recommend something
|
||||
like "MyApp::Type::Foo". We also recommend considering L<MooseX::Types>.
|
||||
|
||||
=head2 Do not coerce Moose built-ins directly
|
||||
|
||||
If you define a coercion for a Moose built-in like C<ArrayRef>, this
|
||||
will affect every application in the Perl interpreter that uses this
|
||||
type.
|
||||
|
||||
# very naughty!
|
||||
coerce 'ArrayRef'
|
||||
=> from Str
|
||||
=> via { [ split /,/ ] };
|
||||
|
||||
Instead, create a subtype and coerce that:
|
||||
|
||||
subtype 'My::ArrayRef' => as 'ArrayRef';
|
||||
|
||||
coerce 'My::ArrayRef'
|
||||
=> from 'Str'
|
||||
=> via { [ split /,/ ] };
|
||||
|
||||
=head2 Do not coerce class names directly
|
||||
|
||||
Just as with Moose built-in types, a class type is global for the
|
||||
entire interpreter. If you add a coercion for that class name, it can
|
||||
have magical side effects elsewhere:
|
||||
|
||||
# also very naughty!
|
||||
coerce 'HTTP::Headers'
|
||||
=> from 'HashRef'
|
||||
=> via { HTTP::Headers->new( %{$_} ) };
|
||||
|
||||
Instead, we can create an "empty" subtype for the coercion:
|
||||
|
||||
subtype 'My::HTTP::Headers' => as class_type('HTTP::Headers');
|
||||
|
||||
coerce 'My::HTTP::Headers'
|
||||
=> from 'HashRef'
|
||||
=> via { HTTP::Headers->new( %{$_} ) };
|
||||
|
||||
=head2 Use coercion instead of unions
|
||||
|
||||
Consider using a type coercion instead of a type union. This was
|
||||
covered in L<Moose::Manual::Types>.
|
||||
|
||||
=head2 Define all your types in one module
|
||||
|
||||
Define all your types and coercions in one module. This was also
|
||||
covered in L<Moose::Manual::Types>.
|
||||
|
||||
=head1 BENEFITS OF BEST PRACTICES
|
||||
|
||||
Following these practices has a number of benefits.
|
||||
|
||||
It helps ensure that your code will play nice with others, making it
|
||||
more reusable and easier to extend.
|
||||
|
||||
Following an accepted set of idioms will make maintenance easier,
|
||||
especially when someone else has to maintain your code. It will also
|
||||
make it easier to get support from other Moose users, since your code
|
||||
will be easier to digest quickly.
|
||||
|
||||
Some of these practices are designed to help Moose do the right thing,
|
||||
especially when it comes to immutabilization. This means your code
|
||||
will be faster when immutabilized.
|
||||
|
||||
Many of these practices also help get the most out of meta
|
||||
programming. If you used an overridden C<new> to do type coercion by
|
||||
hand, rather than defining a real coercion, there is no introspectable
|
||||
metadata. This sort of thing is particularly problematic for MooseX
|
||||
extensions which rely on introspection to do the right thing.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
Stevan Little <stevan@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=item *
|
||||
|
||||
Jesse Luehrs <doy@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Shawn M Moore <sartak@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
|
||||
|
||||
=item *
|
||||
|
||||
Karen Etheridge <ether@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Florian Ragwitz <rafl@debian.org>
|
||||
|
||||
=item *
|
||||
|
||||
Hans Dieter Pearcey <hdp@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Chris Prather <chris@prather.org>
|
||||
|
||||
=item *
|
||||
|
||||
Matt S Trout <mstrout@cpan.org>
|
||||
|
||||
=back
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2006 by Infinity Interactive, Inc.
|
||||
|
||||
This is free software; you can redistribute it and/or modify it under
|
||||
the same terms as the Perl 5 programming language system itself.
|
||||
|
||||
=cut
|
||||
218
CPAN/Moose/Manual/Classes.pod
Normal file
218
CPAN/Moose/Manual/Classes.pod
Normal file
@@ -0,0 +1,218 @@
|
||||
# PODNAME: Moose::Manual::Classes
|
||||
# ABSTRACT: Making your classes use Moose (and subclassing)
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Moose::Manual::Classes - Making your classes use Moose (and subclassing)
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 2.2207
|
||||
|
||||
=head1 USING MOOSE
|
||||
|
||||
Using Moose is very simple, you just C<use Moose>:
|
||||
|
||||
package Person;
|
||||
|
||||
use Moose;
|
||||
|
||||
That's it, you've made a class with Moose!
|
||||
|
||||
There's actually a lot going on here under the hood, so let's step
|
||||
through it.
|
||||
|
||||
When you load L<Moose>, a bunch of sugar functions are exported into your
|
||||
class, such as C<extends>, C<has>, C<with>, and more. These functions are what
|
||||
you use to define your class. For example, you might define an attribute ...
|
||||
|
||||
package Person;
|
||||
|
||||
use Moose;
|
||||
|
||||
has 'ssn' => ( is => 'rw' );
|
||||
|
||||
Attributes are described in the L<Moose::Manual::Attributes>
|
||||
documentation.
|
||||
|
||||
Loading Moose also enables the C<strict> and C<warnings> pragmas in your
|
||||
class.
|
||||
|
||||
When you load Moose, your class will become a subclass of
|
||||
L<Moose::Object>. The L<Moose::Object> class provides a default
|
||||
constructor and destructor, as well as object construction helper
|
||||
methods. You can read more about this in the
|
||||
L<Moose::Manual::Construction> document.
|
||||
|
||||
As a convenience, Moose creates a new class type for your class. See
|
||||
the L<Moose::Manual::Types> document to learn more about types.
|
||||
|
||||
It also creates a L<Moose::Meta::Class> object for your class. This
|
||||
metaclass object is now available by calling a C<meta> method on your
|
||||
class, for example C<< Person->meta >>.
|
||||
|
||||
The metaclass object provides an introspection API for your class. It
|
||||
is also used by Moose itself under the hood to add attributes, define
|
||||
parent classes, and so on. In fact, all of Moose's sugar does the real
|
||||
work by calling methods on this metaclass object (and other meta API
|
||||
objects).
|
||||
|
||||
=head1 SUBCLASSING
|
||||
|
||||
Moose provides a simple sugar function for declaring your parent
|
||||
classes, C<extends>:
|
||||
|
||||
package User;
|
||||
|
||||
use Moose;
|
||||
|
||||
extends 'Person';
|
||||
|
||||
has 'username' => ( is => 'rw' );
|
||||
|
||||
Note that each call to C<extends> will I<reset> your parents. For
|
||||
multiple inheritance you must provide all the parents at once,
|
||||
C<extends 'Foo', 'Bar'>.
|
||||
|
||||
When you call C<extends> Moose will try to load any classes you pass.
|
||||
|
||||
You can use Moose to extend a non-Moose parent. However, when you do
|
||||
this, you will inherit the parent class's constructor (assuming it is
|
||||
also called C<new>). In that case, you will have to take care of
|
||||
initializing attributes manually, either in the parent's constructor,
|
||||
or in your subclass, and you will lose a lot of Moose magic.
|
||||
|
||||
See the L<MooseX::NonMoose> module on CPAN if you're interested in extending
|
||||
non-Moose parent classes with Moose child classes.
|
||||
|
||||
=head1 CLEANING UP MOOSE DROPPINGS
|
||||
|
||||
Moose exports a number of functions into your class. It's a good idea to
|
||||
remove these sugar functions from your class's namespace, so that C<<
|
||||
Person->can('has') >> will no longer return true.
|
||||
|
||||
There are several ways to do this. We recommend using L<namespace::autoclean>,
|
||||
a CPAN module. Not only will it remove Moose exports, it will also remove
|
||||
any other exports.
|
||||
|
||||
package Person;
|
||||
|
||||
use namespace::autoclean;
|
||||
|
||||
use Moose;
|
||||
|
||||
If you absolutely can't use a CPAN module (but can use Moose?), you can write
|
||||
C<no Moose> at the end of your class. This will remove any Moose exports in
|
||||
your class.
|
||||
|
||||
package Person;
|
||||
|
||||
use Moose;
|
||||
|
||||
has 'ssn' => ( is => 'rw' );
|
||||
|
||||
no Moose;
|
||||
|
||||
=head1 MAKING IT FASTER
|
||||
|
||||
Moose has a feature called "immutabilization" that you can use to
|
||||
greatly speed up your classes at runtime. However, using it incurs
|
||||
a cost when your class is first being loaded. When you make your class
|
||||
immutable you tell Moose that you will not be changing it in the
|
||||
future. You will not be adding any more attributes, methods, roles, etc.
|
||||
|
||||
This allows Moose to generate code specific to your class. In
|
||||
particular, it creates an "inline" constructor, making object
|
||||
construction much faster.
|
||||
|
||||
To make your class immutable you simply call C<make_immutable> on your
|
||||
class's metaclass object.
|
||||
|
||||
__PACKAGE__->meta->make_immutable;
|
||||
|
||||
=head2 Immutabilization and C<new()>
|
||||
|
||||
If you override C<new()> in your class, then the immutabilization code
|
||||
will not be able to provide an optimized constructor for your
|
||||
class. Instead, you should use a C<BUILD()> method, which will be
|
||||
called from the inlined constructor.
|
||||
|
||||
Alternately, if you really need to provide a different C<new()>, you
|
||||
can also provide your own immutabilization method. Doing so requires
|
||||
extending the Moose metaclasses, and is well beyond the scope of this
|
||||
manual.
|
||||
|
||||
=head1 INSTANTIATING CLASSES
|
||||
|
||||
When you're ready to use Moose classes in an application, reference them in
|
||||
your code in the regular Perl OO way by including a C<use> directive
|
||||
at the top of the file where the objects should be created.
|
||||
|
||||
use Person;
|
||||
|
||||
my $person = Person->new(
|
||||
# attribute values at instantiation
|
||||
# go here
|
||||
ssn => '123456789',
|
||||
);
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
Stevan Little <stevan@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=item *
|
||||
|
||||
Jesse Luehrs <doy@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Shawn M Moore <sartak@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
|
||||
|
||||
=item *
|
||||
|
||||
Karen Etheridge <ether@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Florian Ragwitz <rafl@debian.org>
|
||||
|
||||
=item *
|
||||
|
||||
Hans Dieter Pearcey <hdp@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Chris Prather <chris@prather.org>
|
||||
|
||||
=item *
|
||||
|
||||
Matt S Trout <mstrout@cpan.org>
|
||||
|
||||
=back
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2006 by Infinity Interactive, Inc.
|
||||
|
||||
This is free software; you can redistribute it and/or modify it under
|
||||
the same terms as the Perl 5 programming language system itself.
|
||||
|
||||
=cut
|
||||
439
CPAN/Moose/Manual/Concepts.pod
Normal file
439
CPAN/Moose/Manual/Concepts.pod
Normal file
@@ -0,0 +1,439 @@
|
||||
# PODNAME: Moose::Manual::Concepts
|
||||
# ABSTRACT: Moose OO concepts
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Moose::Manual::Concepts - Moose OO concepts
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 2.2207
|
||||
|
||||
=head1 MOOSE CONCEPTS (VS "OLD SCHOOL" Perl)
|
||||
|
||||
In the past, you may not have thought too much about the difference
|
||||
between packages and classes, attributes and methods, constructors and
|
||||
methods, etc. With Moose, these are all conceptually separate,
|
||||
though under the hood they're implemented with plain old Perl.
|
||||
|
||||
Our meta-object protocol (aka MOP) provides well-defined introspection
|
||||
features for each of those concepts, and Moose in turn provides
|
||||
distinct sugar for each of them. Moose also introduces additional
|
||||
concepts such as roles, method modifiers, and declarative delegation.
|
||||
|
||||
Knowing what these concepts mean in Moose-speak, and how they used to
|
||||
be done in old school Perl 5 OO is a good way to start learning to use
|
||||
Moose.
|
||||
|
||||
=head2 Class
|
||||
|
||||
When you say "use Moose" in a package, you are making your package a
|
||||
class. At its simplest, a class will consist simply of attributes
|
||||
and/or methods. It can also include roles, method modifiers, and more.
|
||||
|
||||
A class I<has> zero or more B<attributes>.
|
||||
|
||||
A class I<has> zero or more B<methods>.
|
||||
|
||||
A class I<has> zero or more superclasses (aka parent classes). A
|
||||
class inherits from its superclass(es).
|
||||
|
||||
A class I<has> zero or more B<method modifiers>. These modifiers can
|
||||
apply to its own methods or methods that are inherited from its
|
||||
ancestors.
|
||||
|
||||
A class I<does> (and I<consumes>) zero or more B<roles>.
|
||||
|
||||
A class I<has> a B<constructor> and a B<destructor>. These are
|
||||
provided for you "for free" by Moose.
|
||||
|
||||
The B<constructor> accepts named parameters corresponding to the
|
||||
class's attributes and uses them to initialize an B<object instance>.
|
||||
|
||||
A class I<has> a B<metaclass>, which in turn has B<meta-attributes>,
|
||||
B<meta-methods>, and B<meta-roles>. This metaclass I<describes> the
|
||||
class.
|
||||
|
||||
A class is usually analogous to a category of nouns, like "People" or
|
||||
"Users".
|
||||
|
||||
package Person;
|
||||
|
||||
use Moose;
|
||||
# now it's a Moose class!
|
||||
|
||||
=head2 Attribute
|
||||
|
||||
An attribute is a property of the class that defines it. It I<always>
|
||||
has a name, and it I<may have> a number of other properties.
|
||||
|
||||
These properties can include a read/write flag, a B<type>, accessor
|
||||
method names, B<delegations>, a default value, and more.
|
||||
|
||||
Attributes I<are not> methods, but defining them causes various
|
||||
accessor methods to be created. At a minimum, a normal attribute will
|
||||
have a reader accessor method. Many attributes have other
|
||||
methods, such as a writer method, a clearer method, or a predicate method
|
||||
("has it been set?").
|
||||
|
||||
An attribute may also define B<delegations>, which will create
|
||||
additional methods based on the delegation mapping.
|
||||
|
||||
By default, Moose stores attributes in the object instance, which is a
|
||||
hashref, I<but this is invisible to the author of a Moose-based
|
||||
class>! It is best to think of Moose attributes as "properties" of
|
||||
the I<opaque> B<object instance>. These properties are accessed
|
||||
through well-defined accessor methods.
|
||||
|
||||
An attribute is something that the class's members have. For example,
|
||||
People have first and last names. Users have passwords and last login
|
||||
datetimes.
|
||||
|
||||
has 'first_name' => (
|
||||
is => 'rw',
|
||||
isa => 'Str',
|
||||
);
|
||||
|
||||
=head2 Method
|
||||
|
||||
A B<method> is very straightforward. Any subroutine you define in your
|
||||
class is a method.
|
||||
|
||||
B<Methods> correspond to verbs, and are what your objects can do. For
|
||||
example, a User can login.
|
||||
|
||||
sub login { ... }
|
||||
|
||||
=head2 Role
|
||||
|
||||
A role is something that a class I<does>. We also say that classes
|
||||
I<consume> roles. For example, a Machine class might do the Breakable
|
||||
role, and so could a Bone class. A role is used to define some concept
|
||||
that cuts across multiple unrelated classes, like "breakability", or
|
||||
"has a color".
|
||||
|
||||
A role I<has> zero or more B<attributes>.
|
||||
|
||||
A role I<has> zero or more B<methods>.
|
||||
|
||||
A role I<has> zero or more B<method modifiers>.
|
||||
|
||||
A role I<has> zero or more B<required methods>.
|
||||
|
||||
A required method is not implemented by the role. Required methods are a way
|
||||
for the role to declare "to use this role you must implement this method".
|
||||
|
||||
A role I<has> zero or more B<excluded roles>.
|
||||
|
||||
An excluded role is a role that the role doing the excluding says it
|
||||
cannot be combined with.
|
||||
|
||||
Roles are I<composed> into classes (or other roles). When a role is
|
||||
composed into a class, its attributes and methods are "flattened" into
|
||||
the class. Roles I<do not> show up in the inheritance hierarchy. When
|
||||
a role is composed, its attributes and methods appear as if they were
|
||||
defined I<in the consuming class>.
|
||||
|
||||
Role are somewhat like mixins or interfaces in other OO languages.
|
||||
|
||||
package Breakable;
|
||||
|
||||
use Moose::Role;
|
||||
|
||||
requires 'break';
|
||||
|
||||
has 'is_broken' => (
|
||||
is => 'rw',
|
||||
isa => 'Bool',
|
||||
);
|
||||
|
||||
after 'break' => sub {
|
||||
my $self = shift;
|
||||
|
||||
$self->is_broken(1);
|
||||
};
|
||||
|
||||
=head2 Method modifiers
|
||||
|
||||
A B<method modifier> is a hook that is called when a named method is
|
||||
called. For example, you could say "before calling C<login()>, call
|
||||
this modifier first". Modifiers come in different flavors like
|
||||
"before", "after", "around", and "augment", and you can apply more
|
||||
than one modifier to a single method.
|
||||
|
||||
Method modifiers are often used as an alternative to overriding a
|
||||
method in a parent class. They are also used in roles as a way of
|
||||
modifying methods in the consuming class.
|
||||
|
||||
Under the hood, a method modifier is just a plain old Perl subroutine
|
||||
that gets called before or after (or around, etc.) some named method.
|
||||
|
||||
before 'login' => sub {
|
||||
my $self = shift;
|
||||
my $pw = shift;
|
||||
|
||||
warn "Called login() with $pw\n";
|
||||
};
|
||||
|
||||
=head2 Type
|
||||
|
||||
Moose also comes with a (miniature) type system. This allows you to define
|
||||
types for attributes. Moose has a set of built-in types based on the types
|
||||
Perl provides in its core, such as C<Str>, C<Num>, C<Bool>, C<HashRef>, etc.
|
||||
|
||||
In addition, every class name in your application can also be used as
|
||||
a type name.
|
||||
|
||||
Finally, you can define your own types with their own constraints. For
|
||||
example, you could define a C<PosInt> type, a subtype of C<Int> which only
|
||||
allows positive numbers.
|
||||
|
||||
=head2 Delegation
|
||||
|
||||
Moose attributes provide declarative syntax for defining delegations. A
|
||||
delegation is a method which in turn calls some method on an attribute to do
|
||||
its real work.
|
||||
|
||||
=head2 Constructor
|
||||
|
||||
A constructor creates an B<object instance> for the class. In old
|
||||
school Perl, this was usually done by defining a method called
|
||||
C<new()> which in turn called C<bless> on a reference.
|
||||
|
||||
With Moose, this C<new()> method is created for you, and it simply
|
||||
does the right thing. You should never need to define your own
|
||||
constructor!
|
||||
|
||||
Sometimes you want to do something whenever an object is created. In
|
||||
those cases, you can provide a C<BUILD()> method in your class. Moose
|
||||
will call this for you after creating a new object.
|
||||
|
||||
=head2 Destructor
|
||||
|
||||
This is a special method called when an object instance goes out of
|
||||
scope. You can specialize what your class does in this method if you
|
||||
need to, but you usually don't.
|
||||
|
||||
With old school Perl 5, this is the C<DESTROY()> method, but with
|
||||
Moose it is the C<DEMOLISH()> method.
|
||||
|
||||
=head2 Object instance
|
||||
|
||||
An object instance is a specific noun in the class's "category". For
|
||||
example, one specific Person or User. An instance is created by the
|
||||
class's B<constructor>.
|
||||
|
||||
An instance has values for its attributes. For example, a specific
|
||||
person has a first and last name.
|
||||
|
||||
In old school Perl 5, this is often a blessed hash reference. With
|
||||
Moose, you should never need to know what your object instance
|
||||
actually is. (Okay, it's usually a blessed hashref with Moose, too.)
|
||||
|
||||
=head2 Moose vs old school summary
|
||||
|
||||
=over 4
|
||||
|
||||
=item * Class
|
||||
|
||||
A package with no introspection other than mucking about in the symbol
|
||||
table.
|
||||
|
||||
With Moose, you get well-defined declaration and introspection.
|
||||
|
||||
=item * Attributes
|
||||
|
||||
Hand-written accessor methods, symbol table hackery, or a helper
|
||||
module like C<Class::Accessor>.
|
||||
|
||||
With Moose, these are declaratively defined, and distinct from
|
||||
methods.
|
||||
|
||||
=item * Method
|
||||
|
||||
These are pretty much the same in Moose as in old school Perl.
|
||||
|
||||
=item * Roles
|
||||
|
||||
C<Class::Trait> or C<Class::Role>, or maybe C<mixin.pm>.
|
||||
|
||||
With Moose, they're part of the core feature set, and are
|
||||
introspectable like everything else.
|
||||
|
||||
=item * Method Modifiers
|
||||
|
||||
Could only be done through serious symbol table wizardry, and you
|
||||
probably never saw this before (at least in Perl 5).
|
||||
|
||||
=item * Type
|
||||
|
||||
Hand-written parameter checking in your C<new()> method and accessors.
|
||||
|
||||
With Moose, you define types declaratively, and then use them by name
|
||||
with your attributes.
|
||||
|
||||
=item * Delegation
|
||||
|
||||
C<Class::Delegation> or C<Class::Delegator>, but probably even more
|
||||
hand-written code.
|
||||
|
||||
With Moose, this is also declarative.
|
||||
|
||||
=item * Constructor
|
||||
|
||||
A C<new()> method which calls C<bless> on a reference.
|
||||
|
||||
Comes for free when you define a class with Moose.
|
||||
|
||||
=item * Destructor
|
||||
|
||||
A C<DESTROY()> method.
|
||||
|
||||
With Moose, this is called C<DEMOLISH()>.
|
||||
|
||||
=item * Object Instance
|
||||
|
||||
A blessed reference, usually a hash reference.
|
||||
|
||||
With Moose, this is an opaque thing which has a bunch of attributes
|
||||
and methods, as defined by its class.
|
||||
|
||||
=item * Immutabilization
|
||||
|
||||
Moose comes with a feature called "immutabilization". When you make
|
||||
your class immutable, it means you're done adding methods, attributes,
|
||||
roles, etc. This lets Moose optimize your class with a bunch of
|
||||
extremely dirty in-place code generation tricks that speed up things
|
||||
like object construction and so on.
|
||||
|
||||
=back
|
||||
|
||||
=head1 META WHAT?
|
||||
|
||||
A metaclass is a class that describes classes. With Moose, every class you
|
||||
define gets a C<meta()> method. The C<meta()> method returns a
|
||||
L<Moose::Meta::Class> object, which has an introspection API that can tell you
|
||||
about the class it represents.
|
||||
|
||||
my $meta = User->meta();
|
||||
|
||||
for my $attribute ( $meta->get_all_attributes ) {
|
||||
print $attribute->name(), "\n";
|
||||
|
||||
if ( $attribute->has_type_constraint ) {
|
||||
print " type: ", $attribute->type_constraint->name, "\n";
|
||||
}
|
||||
}
|
||||
|
||||
for my $method ( $meta->get_all_methods ) {
|
||||
print $method->name, "\n";
|
||||
}
|
||||
|
||||
Almost every concept we defined earlier has a meta class, so we have
|
||||
L<Moose::Meta::Class>, L<Moose::Meta::Attribute>,
|
||||
L<Moose::Meta::Method>, L<Moose::Meta::Role>,
|
||||
L<Moose::Meta::TypeConstraint>, L<Moose::Meta::Instance>, and so on.
|
||||
|
||||
=head1 BUT I NEED TO DO IT MY WAY!
|
||||
|
||||
One of the great things about Moose is that if you dig down and find
|
||||
that it does something the "wrong way", you can change it by extending
|
||||
a metaclass. For example, you can have arrayref based objects, you can
|
||||
make your constructors strict (no unknown parameters allowed!), you can
|
||||
define a naming scheme for attribute accessors, you can make a class a
|
||||
Singleton, and much, much more.
|
||||
|
||||
Many of these extensions require surprisingly small amounts of code,
|
||||
and once you've done it once, you'll never have to hand-code "your way
|
||||
of doing things" again. Instead you'll just load your favorite
|
||||
extensions.
|
||||
|
||||
package MyWay::User;
|
||||
|
||||
use Moose;
|
||||
use MooseX::StrictConstructor;
|
||||
use MooseX::MyWay;
|
||||
|
||||
has ...;
|
||||
|
||||
=head1 WHAT NEXT?
|
||||
|
||||
So you're sold on Moose. Time to learn how to really use it.
|
||||
|
||||
If you want to see how Moose would translate directly into old school
|
||||
Perl 5 OO code, check out L<Moose::Manual::Unsweetened>. This might be
|
||||
helpful for quickly wrapping your brain around some aspects of "the
|
||||
Moose way".
|
||||
|
||||
Or you can skip that and jump straight to L<Moose::Manual::Classes>
|
||||
and the rest of the L<Moose::Manual>.
|
||||
|
||||
After that we recommend that you start with the L<Moose::Cookbook>. If
|
||||
you work your way through all the recipes under the basics section,
|
||||
you should have a pretty good sense of how Moose works, and all of its
|
||||
basic OO features.
|
||||
|
||||
After that, check out the Role recipes. If you're really curious, go
|
||||
on and read the Meta and Extending recipes, but those are mostly there
|
||||
for people who want to be Moose wizards and extend Moose itself.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
Stevan Little <stevan@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=item *
|
||||
|
||||
Jesse Luehrs <doy@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Shawn M Moore <sartak@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
|
||||
|
||||
=item *
|
||||
|
||||
Karen Etheridge <ether@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Florian Ragwitz <rafl@debian.org>
|
||||
|
||||
=item *
|
||||
|
||||
Hans Dieter Pearcey <hdp@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Chris Prather <chris@prather.org>
|
||||
|
||||
=item *
|
||||
|
||||
Matt S Trout <mstrout@cpan.org>
|
||||
|
||||
=back
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2006 by Infinity Interactive, Inc.
|
||||
|
||||
This is free software; you can redistribute it and/or modify it under
|
||||
the same terms as the Perl 5 programming language system itself.
|
||||
|
||||
=cut
|
||||
228
CPAN/Moose/Manual/Construction.pod
Normal file
228
CPAN/Moose/Manual/Construction.pod
Normal file
@@ -0,0 +1,228 @@
|
||||
# PODNAME: Moose::Manual::Construction
|
||||
# ABSTRACT: Object construction (and destruction) with Moose
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Moose::Manual::Construction - Object construction (and destruction) with Moose
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 2.2207
|
||||
|
||||
=head1 WHERE'S THE CONSTRUCTOR?
|
||||
|
||||
B<Do not define a C<new()> method for your classes!>
|
||||
|
||||
When you C<use Moose> in your class, your class becomes a subclass of
|
||||
L<Moose::Object>. The L<Moose::Object> provides a C<new()> method for your
|
||||
class. If you follow our recommendations in L<Moose::Manual::BestPractices>
|
||||
and make your class immutable, then you actually get a class-specific C<new()>
|
||||
method "inlined" in your class.
|
||||
|
||||
=head1 OBJECT CONSTRUCTION AND ATTRIBUTES
|
||||
|
||||
The Moose-provided constructor accepts a hash or hash reference of
|
||||
named parameters matching your attributes (actually, matching their
|
||||
C<init_arg>s). This is just another way in which Moose keeps you from
|
||||
worrying I<how> classes are implemented. Simply define a class and
|
||||
you're ready to start creating objects!
|
||||
|
||||
=head1 OBJECT CONSTRUCTION HOOKS
|
||||
|
||||
Moose lets you hook into object construction. You can validate an
|
||||
object's state, do logging, customize construction from parameters which
|
||||
do not match your attributes, or maybe allow non-hash(ref) constructor
|
||||
arguments. You can do this by creating C<BUILD> and/or C<BUILDARGS>
|
||||
methods.
|
||||
|
||||
If these methods exist in your class, Moose will arrange for them to
|
||||
be called as part of the object construction process.
|
||||
|
||||
=head2 BUILDARGS
|
||||
|
||||
The C<BUILDARGS> method is called as a class method I<before> an
|
||||
object is created. It will receive all of the arguments that were
|
||||
passed to C<new()> I<as-is>, and is expected to return a hash
|
||||
reference. This hash reference will be used to construct the object,
|
||||
so it should contain keys matching your attributes' names (well,
|
||||
C<init_arg>s).
|
||||
|
||||
One common use for C<BUILDARGS> is to accommodate a non-hash(ref)
|
||||
calling style. For example, we might want to allow our Person class to
|
||||
be called with a single argument of a social security number, C<<
|
||||
Person->new($ssn) >>.
|
||||
|
||||
Without a C<BUILDARGS> method, Moose will complain, because it expects
|
||||
a hash or hash reference. We can use the C<BUILDARGS> method to
|
||||
accommodate this calling style:
|
||||
|
||||
around BUILDARGS => sub {
|
||||
my $orig = shift;
|
||||
my $class = shift;
|
||||
|
||||
if ( @_ == 1 && !ref $_[0] ) {
|
||||
return $class->$orig( ssn => $_[0] );
|
||||
}
|
||||
else {
|
||||
return $class->$orig(@_);
|
||||
}
|
||||
};
|
||||
|
||||
Note the call to C<< $class->$orig >>. This will call the default C<BUILDARGS>
|
||||
in L<Moose::Object>. This method takes care of distinguishing between a hash
|
||||
reference and a plain hash for you.
|
||||
|
||||
=head2 BUILD
|
||||
|
||||
The C<BUILD> method is called I<after> an object is created. There are
|
||||
several reasons to use a C<BUILD> method. One of the most common is to
|
||||
check that the object state is valid. While we can validate individual
|
||||
attributes through the use of types, we can't validate the state of a
|
||||
whole object that way.
|
||||
|
||||
sub BUILD {
|
||||
my $self = shift;
|
||||
|
||||
if ( $self->country_of_residence eq 'USA' ) {
|
||||
die 'All US residents must have an SSN'
|
||||
unless $self->has_ssn;
|
||||
}
|
||||
}
|
||||
|
||||
Another use of a C<BUILD> method could be for logging or tracking
|
||||
object creation.
|
||||
|
||||
sub BUILD {
|
||||
my $self = shift;
|
||||
|
||||
debug( 'Made a new person - SSN = ', $self->ssn, );
|
||||
}
|
||||
|
||||
The C<BUILD> method is called with the hash reference of the parameters passed
|
||||
to the constructor (after munging by C<BUILDARGS>). This gives you a chance to
|
||||
do something with parameters that do not represent object attributes.
|
||||
|
||||
sub BUILD {
|
||||
my $self = shift;
|
||||
my $args = shift;
|
||||
|
||||
$self->add_friend(
|
||||
My::User->new(
|
||||
user_id => $args->{user_id},
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
=head3 BUILD and parent classes
|
||||
|
||||
The interaction between multiple C<BUILD> methods in an inheritance hierarchy
|
||||
is different from normal Perl methods. B<You should never call C<<
|
||||
$self->SUPER::BUILD >>>, nor should you ever apply a method modifier to
|
||||
C<BUILD>. Roles are an exception to this rule, though: it's completely
|
||||
acceptable to apply a method modifier to C<BUILD> in a role; you can
|
||||
even provide an empty C<BUILD> subroutine in a role so the role is applicable
|
||||
even to classes without their own C<BUILD>.
|
||||
|
||||
Moose arranges to have all of the C<BUILD> methods in a hierarchy
|
||||
called when an object is constructed, I<from parents to
|
||||
children>. This might be surprising at first, because it reverses the
|
||||
normal order of method inheritance.
|
||||
|
||||
The theory behind this is that C<BUILD> methods can only be used for
|
||||
increasing specialization of a class's constraints, so it makes sense
|
||||
to call the least specific C<BUILD> method first. Also, this is how
|
||||
Perl 6 does it.
|
||||
|
||||
=head1 OBJECT DESTRUCTION
|
||||
|
||||
Moose provides a hook for object destruction with the C<DEMOLISH>
|
||||
method. As with C<BUILD>, you should never explicitly call C<<
|
||||
$self->SUPER::DEMOLISH >>. Moose will arrange for all of the
|
||||
C<DEMOLISH> methods in your hierarchy to be called, from most to least
|
||||
specific.
|
||||
|
||||
Each C<DEMOLISH> method is called with a single argument. This is a boolean
|
||||
value indicating whether or not this method was called as part of the global
|
||||
destruction process (when the Perl interpreter exits).
|
||||
|
||||
In most cases, Perl's built-in garbage collection is sufficient, and
|
||||
you won't need to provide a C<DEMOLISH> method.
|
||||
|
||||
=head2 Error Handling During Destruction
|
||||
|
||||
The interaction of object destruction and Perl's global C<$@> and C<$?>
|
||||
variables can be very confusing.
|
||||
|
||||
Moose always localizes C<$?> when an object is being destroyed. This means
|
||||
that if you explicitly call C<exit>, that exit code will be preserved even if
|
||||
an object's destructor makes a system call.
|
||||
|
||||
Moose also preserves C<$@> against any C<eval> calls that may happen during
|
||||
object destruction. However, if an object's C<DEMOLISH> method actually dies,
|
||||
Moose explicitly rethrows that error.
|
||||
|
||||
If you do not like this behavior, you will have to provide your own C<DESTROY>
|
||||
method and use that instead of the one provided by L<Moose::Object>. You can
|
||||
do this to preserve C<$@> I<and> capture any errors from object destruction by
|
||||
creating an error stack.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
Stevan Little <stevan@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=item *
|
||||
|
||||
Jesse Luehrs <doy@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Shawn M Moore <sartak@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
|
||||
|
||||
=item *
|
||||
|
||||
Karen Etheridge <ether@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Florian Ragwitz <rafl@debian.org>
|
||||
|
||||
=item *
|
||||
|
||||
Hans Dieter Pearcey <hdp@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Chris Prather <chris@prather.org>
|
||||
|
||||
=item *
|
||||
|
||||
Matt S Trout <mstrout@cpan.org>
|
||||
|
||||
=back
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2006 by Infinity Interactive, Inc.
|
||||
|
||||
This is free software; you can redistribute it and/or modify it under
|
||||
the same terms as the Perl 5 programming language system itself.
|
||||
|
||||
=cut
|
||||
545
CPAN/Moose/Manual/Contributing.pod
Normal file
545
CPAN/Moose/Manual/Contributing.pod
Normal file
@@ -0,0 +1,545 @@
|
||||
# PODNAME: Moose::Manual::Contributing
|
||||
# ABSTRACT: How to get involved in Moose
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Moose::Manual::Contributing - How to get involved in Moose
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 2.2207
|
||||
|
||||
=for comment CONTRIBUTING.pod is generated from lib/Moose/Manual/Contributing.pod
|
||||
|
||||
=head1 GETTING INVOLVED
|
||||
|
||||
Moose is an open project, and we are always willing to accept bug fixes,
|
||||
more tests, and documentation patches. Commit bits are given out freely and
|
||||
it's easy to get started!
|
||||
|
||||
=head2 Get the Code
|
||||
|
||||
If you just want to get your feet wet and check out the code, you can do so
|
||||
from the comfort of your web browser by going to the official repository on
|
||||
GitHub: L<https://github.com/moose/Moose>.
|
||||
|
||||
However, if you know how to use git and would rather have a local copy
|
||||
(because, why wouldn't you?!), then you can clone it:
|
||||
|
||||
git clone git@github.com:moose/Moose.git
|
||||
|
||||
If, at some point, you think you'd like to contribute a patch, please see
|
||||
L</Getting Started>.
|
||||
|
||||
I<B<NOTE:> Your contribution is very important to us. If, for some reason,
|
||||
you would prefer not to use Git/GitHub, come talk to us at #moose on
|
||||
irc.perl.org and we can work something out.>
|
||||
|
||||
=head2 People
|
||||
|
||||
As Moose has matured, some structure has emerged in the process.
|
||||
|
||||
=over
|
||||
|
||||
=item Cabal - people who can release moose
|
||||
|
||||
These people are the ones who have co-maint on Moose itself and can create a
|
||||
release. They're listed under L<Moose/CABAL> in the Moose documentation. They
|
||||
are responsible for reviewing branches, and are the only people who are
|
||||
allowed to push to stable branches.
|
||||
|
||||
Cabal members are listed in L<Moose> and can often be found on irc in the
|
||||
L<irc://irc.perl.org/#moose-dev> channel.
|
||||
|
||||
=item Contributors - people creating a topic or branch
|
||||
|
||||
You!
|
||||
|
||||
=back
|
||||
|
||||
=head2 New Features
|
||||
|
||||
Moose already has a fairly large feature set, and we are currently
|
||||
B<not> looking to add any major new features to it. If you have an
|
||||
idea for a new feature in Moose, you are encouraged to create a
|
||||
MooseX module first.
|
||||
|
||||
At this stage, no new features will even be considered for addition
|
||||
into the core without first being vetted as a MooseX module, unless
|
||||
it is absolutely 100% impossible to implement the feature outside the
|
||||
core.
|
||||
|
||||
If you think it is 100% impossible, please come discuss it with us on IRC or
|
||||
via e-mail. Your feature may need a small hook in the core, or a
|
||||
refactoring of some core modules, and we are definitely open to that.
|
||||
|
||||
Moose was built from the ground up with the idea of being highly extensible,
|
||||
and quite often the feature requests we see can be implemented through small
|
||||
extensions. Try it, it's much easier than you might think.
|
||||
|
||||
=head2 Branch Layout
|
||||
|
||||
The repository is divided into several branches to make maintenance easier for
|
||||
everyone involved. The branches below are ordered by level of stability.
|
||||
|
||||
=over
|
||||
|
||||
=item stable/*
|
||||
|
||||
The branch from which releases are cut. When making a new major release, the
|
||||
release manager makes a new C<stable/X.YY> branch at the current position of
|
||||
C<master>. The version used in the stable branch should not include the last
|
||||
two digits of the version number.
|
||||
|
||||
For minor releases, patches will be committed to C<master>, and
|
||||
backported (cherry-picked) to the appropriate stable branch as needed. A
|
||||
stable branch is only updated by someone from the Cabal during a release.
|
||||
|
||||
=item master
|
||||
|
||||
The main development branch. All new code should be written against this
|
||||
branch. This branch contains code that has been reviewed, and will be included
|
||||
in the next major release. Commits which are judged to not break backwards
|
||||
compatibility may be backported into C<stable> to be included in the next minor
|
||||
release.
|
||||
|
||||
=item topic/*
|
||||
|
||||
Small personal branches that are still in progress. They can be freely rebased.
|
||||
They contain targeted features that may span a handful of commits. Any change
|
||||
or bugfix should be created in a topic branch.
|
||||
|
||||
=item rfc/*
|
||||
|
||||
Topic branches that are completed and waiting on review. A Cabal member will
|
||||
look over branches in this namespace, and either merge them to C<master> if
|
||||
they are acceptable, or move them back to a different namespace otherwise.
|
||||
This namespace is being phased out now that we are using GitHub's pull
|
||||
requests in our L</Development Workflow>.
|
||||
|
||||
=item attic/*
|
||||
|
||||
Branches which have been reviewed, and rejected. They remain in the repository
|
||||
in case we later change our mind, or in case parts of them are still useful.
|
||||
|
||||
=item abandoned/*
|
||||
|
||||
Topic branches which have had no activity for a long period of time will be
|
||||
moved here, to keep the main areas clean.
|
||||
|
||||
=back
|
||||
|
||||
Larger, longer term branches can also be created in the root namespace (i.e.
|
||||
at the same level as master and stable). This may be appropriate if multiple
|
||||
people are intending to work on the branch. These branches should not be
|
||||
rebased without checking with other developers first.
|
||||
|
||||
=head1 WORKFLOWS
|
||||
|
||||
=head2 Getting Started
|
||||
|
||||
So, you've cloned the main Moose repository to your local machine (see
|
||||
L</Get the Code>) and you're ready to do some hacking. We couldn't be
|
||||
happier to welcome you to our community!
|
||||
|
||||
Of course, to ensure that your first experience is as productive and
|
||||
satisfying as possible, you should probably take some time to read over this
|
||||
entire POD document. Doing so will give you a full understanding of how Moose
|
||||
developers and maintainers work together and what they expect from one
|
||||
another. Done? Great!
|
||||
|
||||
Next, assuming you have a GitHub account, go to
|
||||
L<http://github.com/moose/Moose> and B<fork the repository> (see
|
||||
L<https://help.github.com/articles/fork-a-repo>). This will put an exact
|
||||
replica of the Moose repository into your GitHub account, which will serve as
|
||||
a place to publish your patches for the Moose maintainers to review and
|
||||
incorporate.
|
||||
|
||||
Once your fork has been created, switch to your local working repository directory
|
||||
and update your C<origin> remote's push URL. This allows you to use a single
|
||||
remote (C<origin>) to both pull in the latest code from GitHub and also push
|
||||
your work to your own fork:
|
||||
|
||||
# Replace YOUR_USERNAME below with your GitHub username
|
||||
git remote set-url --push origin git@github.com:YOUR_USERNAME/moose.git
|
||||
|
||||
You can verify your work:
|
||||
|
||||
$ git remote -v
|
||||
origin git@github.com:moose/Moose.git (fetch)
|
||||
origin git@github.com:YOUR_USERNAME/moose.git (push)
|
||||
|
||||
Now, you're ready for action! From now on, you just follow the L</Development
|
||||
Workflow> to publish your work and B<submit pull requests> to the Moose Cabal.
|
||||
|
||||
=head2 Development Workflow
|
||||
|
||||
The general gist of the B<STANDARD WORKFLOW> is:
|
||||
|
||||
=over 4
|
||||
|
||||
=item 1. Update your local repository with the latest commits from the official repository
|
||||
|
||||
=item 2. Create a new topic branch, based on the master branch
|
||||
|
||||
=item 3. Hack away
|
||||
|
||||
=item 4. Commit and push the topic branch to your forked repository
|
||||
|
||||
=item 5. Submit a pull request through GitHub for that branch
|
||||
|
||||
=back
|
||||
|
||||
What follows is a more detailed rundown of that workflow. Please make sure to
|
||||
review and follow the steps in the previous section, L</Getting Started>, if
|
||||
you have not done so already.
|
||||
|
||||
=head3 Update Your Repository
|
||||
|
||||
Update your local copy of the master branch from the remote:
|
||||
|
||||
git checkout master
|
||||
git pull --rebase
|
||||
|
||||
=head3 Create Your Topic Branch
|
||||
|
||||
Now, create a new topic branch based on your master branch. It's useful to
|
||||
use concise, descriptive branch names such as: pod-syntax-contrib,
|
||||
feat-autodelegation, patch-23-role-comp, etc. However, we'll just call ours
|
||||
C<my-feature> for demonstration purposes:
|
||||
|
||||
git checkout -b topic/my-feature
|
||||
|
||||
=head3 Hack. Commit. Repeat.
|
||||
|
||||
While you're hacking, the most important thing to remember is that your topic
|
||||
branch is yours to do with as you like. Nothing you do there will affect
|
||||
anyone else at this point. Commit as often as little or as often as you need
|
||||
to and don't let perfection get in the way of progress. However, don't try to
|
||||
do too much as the easiest changes to integrate are small and focused.
|
||||
|
||||
If it's been a while since you created your topic branch, it's often a good
|
||||
idea to periodically rebase your branch off of the upstream master to reduce
|
||||
your work later on:
|
||||
|
||||
git fetch # or, git remote update
|
||||
git rebase origin/master # or, git pull --rebase origin master
|
||||
|
||||
You should also feel free to publish (using C<push --force> if necessary) your
|
||||
branch to your GitHub fork if you simply need feedback from others. (Note:
|
||||
actual collaboration takes a bit more finesse and a lot less C<--force>
|
||||
however).
|
||||
|
||||
=head3 Clean Up Your Branch
|
||||
|
||||
Finally, when your development is done, it's time to prepare your branch for
|
||||
review. Even the smallest branches can often use a little bit of tidying up
|
||||
before they are unleashed on a reviewer. Clarifying/cleaning up commit
|
||||
messages, reordering commits, splitting large commits or those which contain
|
||||
different types of changes, squashing related or straggler commits are all
|
||||
B<highly> worthwhile activities to undertake on your topic branch.
|
||||
|
||||
B<Remember:> Your topic branch is yours. Don't worry about rewriting its
|
||||
history or breaking fast-forward. Some useful commands are listed below but
|
||||
please make sure that you understand what they do as they can rewrite history:
|
||||
|
||||
- git commit --amend
|
||||
- git rebase --interactive
|
||||
- git cherry-pick
|
||||
|
||||
Ultimately, your goal in cleaning up your branch is to craft a set of commits
|
||||
whose content and messages are as focused and understandable as possible.
|
||||
Doing so will greatly increase the chances of a speedy review and acceptance
|
||||
into the mainline development.
|
||||
|
||||
=head3 Rebase on the Latest
|
||||
|
||||
Before your final push and issuing a pull request, you need to ensure that
|
||||
your changes can be easily merged into the master branch of the upstream
|
||||
repository. This is done by once again rebasing your branch on the latest
|
||||
C<origin/master>.
|
||||
|
||||
git fetch # or, git remote update
|
||||
git rebase origin/master # or, git pull --rebase origin master
|
||||
|
||||
=head3 Publish and Pull Request
|
||||
|
||||
Now it's time to make your final push of the branch to your fork. The
|
||||
C<--force> flag is only necessary if you've pushed before and subsequently
|
||||
rewriting your history:
|
||||
|
||||
git push --force
|
||||
|
||||
After your branch is published, you can issue a pull request to the Moose
|
||||
Cabal. See <https://help.github.com/articles/using-pull-requests> for details.
|
||||
|
||||
Congratulations! You're now a contributor!
|
||||
|
||||
=head2 Approval Workflow
|
||||
|
||||
Moose is an open project but it is also an increasingly important one. Many
|
||||
modules depend on Moose being stable. Therefore, we have a basic set of
|
||||
criteria for reviewing and merging branches. What follows is a set of rough
|
||||
guidelines that ensures all new code is properly vetted before it is merged to
|
||||
the master branch.
|
||||
|
||||
It should be noted that if you want your specific branch to be approved, it is
|
||||
B<your> responsibility to follow this process and advocate for your branch.
|
||||
|
||||
=over 4
|
||||
|
||||
=item Small bug fixes, doc patches and additional passing tests.
|
||||
|
||||
These items don't really require approval beyond one of the core contributors
|
||||
just doing a simple review. For especially simple patches (doc patches
|
||||
especially), committing directly to master is fine.
|
||||
|
||||
=item Larger bug fixes, doc additions and TODO or failing tests.
|
||||
|
||||
Larger bug fixes should be reviewed by at least one cabal member and should be
|
||||
tested using the F<xt/author/test-my-dependents.t> test.
|
||||
|
||||
New documentation is always welcome, but should also be reviewed by a cabal
|
||||
member for accuracy.
|
||||
|
||||
TODO tests are basically feature requests, see our L</New Features> section
|
||||
for more information on that. If your feature needs core support, create a
|
||||
C<topic/> branch using the L</Development Workflow> and start hacking away.
|
||||
|
||||
Failing tests are basically bug reports. You should find a core contributor
|
||||
and/or cabal member to see if it is a real bug, then submit the bug and your
|
||||
test to the RT queue. Source control is not a bug reporting tool.
|
||||
|
||||
=item New user-facing features.
|
||||
|
||||
Anything that creates a new user-visible feature needs to be approved by
|
||||
B<more than one> cabal member.
|
||||
|
||||
Make sure you have reviewed L</New Features> to be sure that you are following
|
||||
the guidelines. Do not be surprised if a new feature is rejected for the core.
|
||||
|
||||
=item New internals features.
|
||||
|
||||
New features for Moose internals are less restrictive than user facing
|
||||
features, but still require approval by B<at least one> cabal member.
|
||||
|
||||
Ideally you will have run the F<xt/author/test-my-dependents.t> script to be sure you
|
||||
are not breaking any MooseX module or causing any other unforeseen havoc. If
|
||||
you do this (rather than make us do it), it will only help to hasten your
|
||||
branch's approval.
|
||||
|
||||
=item Backwards incompatible changes.
|
||||
|
||||
Anything that breaks backwards compatibility must be discussed by the
|
||||
cabal. Backwards incompatible changes should not be merged to master if there
|
||||
are strong objections from any cabal members.
|
||||
|
||||
We have a policy for what we see as sane L</BACKWARDS COMPATIBILITY> for
|
||||
Moose. If your changes break back-compat, you must be ready to discuss and
|
||||
defend your change.
|
||||
|
||||
=back
|
||||
|
||||
=head2 Release Workflow
|
||||
|
||||
# major releases (including trial releases)
|
||||
git checkout master
|
||||
|
||||
# minor releases
|
||||
git checkout stable/X.YY
|
||||
|
||||
# do final changelogging, etc
|
||||
git commit
|
||||
dzil release # or dzil release --trial for trial releases
|
||||
|
||||
=head3 Release How-To
|
||||
|
||||
Moose uses L<Dist::Zilla> to manage releases. Although the git repository comes
|
||||
with a C<Makefile.PL>, it is a very basic one just to allow the basic
|
||||
C<perl Makefile.PL && make && make test> cycle to work. In particular, it
|
||||
doesn't include any release metadata, such as dependencies. In order to get
|
||||
started with Dist::Zilla, first install it: C<cpanm Dist::Zilla>, and then
|
||||
install the plugins necessary for reading the C<dist.ini>:
|
||||
C<dzil authordeps | cpanm>.
|
||||
|
||||
Moose releases fall into two categories, each with their own level of release
|
||||
preparation. A minor release is one which does not include any API changes,
|
||||
deprecations, and so on. In that case, it is sufficient to simply test the
|
||||
release candidate against a few different Perls. Testing should be done against
|
||||
at least two recent major versions of Perl (5.8.8 and 5.10.1, for example). If
|
||||
you have more versions available, you are encouraged to test them all. However,
|
||||
we do not put a lot of effort into supporting older 5.8.x releases.
|
||||
|
||||
For major releases which include an API change or deprecation, you should run
|
||||
the F<xt/author/test-my-dependents.t> test. This tests a long list of MooseX
|
||||
and other Moose-using modules from CPAN. In order to run this script, you must
|
||||
arrange to have the new version of Moose in Perl's include path. You can use
|
||||
C<prove -b> and C<prove -I>, install the module, or fiddle with the C<PERL5LIB>
|
||||
environment variable, whatever makes you happy.
|
||||
|
||||
This test downloads each module from CPAN, runs its tests, and logs failures
|
||||
and warnings to a set of files named F<test-mydeps-$$-*.log>. If there are
|
||||
failures or warnings, please work with the authors of the modules in question
|
||||
to fix them. If the module author simply isn't available or does not want to
|
||||
fix the bug, it is okay to make a release.
|
||||
|
||||
Regardless of whether or not a new module is available, any breakages should
|
||||
be noted in the conflicts list in the distribution's F<dist.ini>.
|
||||
|
||||
=head2 Emergency Bug Workflow (for immediate release)
|
||||
|
||||
The stable branch exists for easily making bug fix releases.
|
||||
|
||||
git remote update
|
||||
git checkout -b topic/my-emergency-fix origin/master
|
||||
# hack
|
||||
git commit
|
||||
|
||||
Then a cabal member merges into C<master>, and backports the change into
|
||||
C<stable/X.YY>:
|
||||
|
||||
git checkout master
|
||||
git merge topic/my-emergency-fix
|
||||
git push
|
||||
git checkout stable/X.YY
|
||||
git cherry-pick -x master
|
||||
git push
|
||||
# release
|
||||
|
||||
=head2 Project Workflow
|
||||
|
||||
For longer lasting branches, we use a subversion style branch layout, where
|
||||
master is routinely merged into the branch. Rebasing is allowed as long as all
|
||||
the branch contributors are using C<git pull --rebase> properly.
|
||||
|
||||
C<commit --amend>, C<rebase --interactive>, etc. are not allowed, and should
|
||||
only be done in topic branches. Committing to master is still done with the
|
||||
same review process as a topic branch, and the branch must merge as a fast
|
||||
forward.
|
||||
|
||||
This is pretty much the way we're doing branches for large-ish things right
|
||||
now.
|
||||
|
||||
Obviously there is no technical limitation on the number of branches. You can
|
||||
freely create topic branches off of project branches, or sub projects inside
|
||||
larger projects freely. Such branches should incorporate the name of the branch
|
||||
they were made off so that people don't accidentally assume they should be
|
||||
merged into master:
|
||||
|
||||
git checkout -b my-project--topic/foo my-project
|
||||
|
||||
(unfortunately Git will not allow C<my-project/foo> as a branch name if
|
||||
C<my-project> is a valid ref).
|
||||
|
||||
=head1 BRANCH ARCHIVAL
|
||||
|
||||
Merged branches should be deleted.
|
||||
|
||||
Failed branches may be kept, but should be moved to C<attic/> to differentiate
|
||||
them from in-progress topic branches.
|
||||
|
||||
Branches that have not been worked on for a long time will be moved to
|
||||
C<abandoned/> periodically, but feel free to move the branch back to C<topic/>
|
||||
if you want to start working on it again.
|
||||
|
||||
=head1 TESTS, TESTS, TESTS
|
||||
|
||||
If you write I<any> code for Moose, you B<must> add tests for that code. If you
|
||||
do not write tests then we cannot guarantee your change will not be removed or
|
||||
altered at a later date, as there is nothing to confirm this is desired
|
||||
behavior.
|
||||
|
||||
If your code change/addition is deep within the bowels of Moose and your test
|
||||
exercises this feature in a non-obvious way, please add some comments either
|
||||
near the code in question or in the test so that others know.
|
||||
|
||||
We also greatly appreciate documentation to go with your changes, and an entry
|
||||
in the Changes file. Make sure to give yourself credit! Major changes or new
|
||||
user-facing features should also be documented in L<Moose::Manual::Delta>.
|
||||
|
||||
=head1 DOCS, DOCS, DOCS
|
||||
|
||||
Any user-facing changes must be accompanied by documentation. If you're not
|
||||
comfortable writing docs yourself, you might be able to convince another Moose
|
||||
dev to help you.
|
||||
|
||||
Our goal is to make sure that all features are documented. Undocumented
|
||||
features are not considered part of the API when it comes to determining
|
||||
whether a change is backwards compatible.
|
||||
|
||||
=head1 BACKWARDS COMPATIBILITY
|
||||
|
||||
Change is inevitable, and Moose is not immune to this. We do our best
|
||||
to maintain backwards compatibility, but we do not want the code base
|
||||
to become overburdened by this. This is not to say that we will be
|
||||
frivolous with our changes, quite the opposite, just that we are not
|
||||
afraid of change and will do our best to keep it as painless as
|
||||
possible for the end user.
|
||||
|
||||
Our policy for handling backwards compatibility is documented in more detail in
|
||||
L<Moose::Manual::Support>.
|
||||
|
||||
All backwards incompatible changes B<must> be documented in
|
||||
L<Moose::Manual::Delta>. Make sure to document any useful tips or workarounds
|
||||
for the change in that document.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
Stevan Little <stevan@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=item *
|
||||
|
||||
Jesse Luehrs <doy@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Shawn M Moore <sartak@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
|
||||
|
||||
=item *
|
||||
|
||||
Karen Etheridge <ether@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Florian Ragwitz <rafl@debian.org>
|
||||
|
||||
=item *
|
||||
|
||||
Hans Dieter Pearcey <hdp@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Chris Prather <chris@prather.org>
|
||||
|
||||
=item *
|
||||
|
||||
Matt S Trout <mstrout@cpan.org>
|
||||
|
||||
=back
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2006 by Infinity Interactive, Inc.
|
||||
|
||||
This is free software; you can redistribute it and/or modify it under
|
||||
the same terms as the Perl 5 programming language system itself.
|
||||
|
||||
=cut
|
||||
313
CPAN/Moose/Manual/Delegation.pod
Normal file
313
CPAN/Moose/Manual/Delegation.pod
Normal file
@@ -0,0 +1,313 @@
|
||||
# PODNAME: Moose::Manual::Delegation
|
||||
# ABSTRACT: Attribute delegation
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Moose::Manual::Delegation - Attribute delegation
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 2.2207
|
||||
|
||||
=head1 WHAT IS DELEGATION?
|
||||
|
||||
Delegation is a feature that lets you create "proxy" methods that do nothing
|
||||
more than call some other method on an attribute. This lets you simplify a
|
||||
complex set of "has-a" relationships and present a single unified API from one
|
||||
class.
|
||||
|
||||
With delegation, consumers of a class don't need to know about all the
|
||||
objects it contains, reducing the amount of API they need to learn.
|
||||
|
||||
Delegations are defined as a mapping between one or more methods
|
||||
provided by the "real" class (the delegatee), and a set of
|
||||
corresponding methods in the delegating class. The delegating class
|
||||
can re-use the method names provided by the delegatee or provide its
|
||||
own names.
|
||||
|
||||
Delegation is also a great way to wrap an existing class, especially a
|
||||
non-Moose class or one that is somehow hard (or impossible) to
|
||||
subclass.
|
||||
|
||||
=head1 DEFINING A MAPPING
|
||||
|
||||
Moose offers a number of options for defining a delegation's mapping,
|
||||
ranging from simple to complex.
|
||||
|
||||
The simplest form is to simply specify a list of methods:
|
||||
|
||||
package Website;
|
||||
|
||||
use Moose;
|
||||
|
||||
has 'uri' => (
|
||||
is => 'ro',
|
||||
isa => 'URI',
|
||||
handles => [qw( host path )],
|
||||
);
|
||||
|
||||
Using an arrayref tells Moose to create methods in your class that match the
|
||||
method names in the delegated class.
|
||||
|
||||
With this definition, we can call C<< $website->host >> and it "just
|
||||
works". Under the hood, Moose will call C<< $website->uri->host >> for
|
||||
you. Note that C<$website> is I<not> automatically passed to the C<host>
|
||||
method; the invocant is C<< $website->uri >>.
|
||||
|
||||
We can also define a mapping as a hash reference. This allows you to
|
||||
rename methods as part of the mapping:
|
||||
|
||||
package Website;
|
||||
|
||||
use Moose;
|
||||
|
||||
has 'uri' => (
|
||||
is => 'ro',
|
||||
isa => 'URI',
|
||||
handles => {
|
||||
hostname => 'host',
|
||||
path => 'path',
|
||||
},
|
||||
);
|
||||
|
||||
Using a hash tells Moose to create method names (specified on the left) which
|
||||
invoke the delegated class methods (specified on the right).
|
||||
|
||||
In this example, we've created a C<< $website->hostname >> method,
|
||||
rather than simply using C<URI.pm>'s name, C<host> in the Website
|
||||
class.
|
||||
|
||||
These two mapping forms are the ones you will use most often. The
|
||||
remaining methods are a bit more complex.
|
||||
|
||||
has 'uri' => (
|
||||
is => 'ro',
|
||||
isa => 'URI',
|
||||
handles => qr/^(?:host|path|query.*)/,
|
||||
);
|
||||
|
||||
This is similar to the array version, except it uses the regex to
|
||||
match against all the methods provided by the delegatee. In order for
|
||||
this to work, you must provide an C<isa> parameter for the attribute,
|
||||
and it must be a class. Moose uses this to introspect the delegatee
|
||||
class and determine what methods it provides.
|
||||
|
||||
You can use a role name as the value of C<handles>:
|
||||
|
||||
has 'uri' => (
|
||||
is => 'ro',
|
||||
isa => 'URI',
|
||||
handles => 'HasURI',
|
||||
);
|
||||
|
||||
Moose will introspect the role to determine what methods it provides
|
||||
and create a name-for-name mapping for each of those methods.
|
||||
|
||||
Finally, you can provide a sub reference to I<generate> a mapping that behaves
|
||||
like the hash example above. You probably won't need this version often (if
|
||||
ever). See the L<Moose> docs for more details on exactly how this works.
|
||||
|
||||
=head1 NATIVE DELEGATION
|
||||
|
||||
Native delegations allow you to delegate to standard Perl data structures as
|
||||
if they were objects.
|
||||
|
||||
has 'queue' => (
|
||||
traits => ['Array'],
|
||||
isa => 'ArrayRef[Item]',
|
||||
default => sub { [ ] },
|
||||
handles => {
|
||||
add_item => 'push',
|
||||
next_item => 'shift',
|
||||
},
|
||||
)
|
||||
|
||||
The C<Array> trait in the C<traits> parameter tells Moose that you would like
|
||||
to use the set of Array helpers. Moose will then create C<add_item> and
|
||||
C<next_item> methods that "just work". Behind the scenes C<add_item> is
|
||||
something like
|
||||
|
||||
sub add_item {
|
||||
my ($self, @items) = @_;
|
||||
|
||||
for my $item (@items) {
|
||||
$Item_TC->validate($item);
|
||||
}
|
||||
|
||||
push @{ $self->queue }, @items;
|
||||
}
|
||||
|
||||
For example, you might use Array helpers to add C<add_task> and
|
||||
C<add_appointment> methods to a Calendar class:
|
||||
|
||||
has 'tasks' => (
|
||||
traits => ['Array'],
|
||||
isa => 'ArrayRef[Task]',
|
||||
default => sub { [ ] },
|
||||
handles => {
|
||||
add_task => 'push',
|
||||
next_task => 'shift',
|
||||
},
|
||||
);
|
||||
|
||||
has 'appointments' => (
|
||||
traits => ['Array'],
|
||||
isa => 'ArrayRef[Appointment]',
|
||||
default => sub { [ ] },
|
||||
handles => {
|
||||
add_appointment => 'push',
|
||||
next_appointment => 'shift',
|
||||
},
|
||||
);
|
||||
|
||||
Which you would call as:
|
||||
|
||||
$calendar->add_task( $task_obj );
|
||||
$calendar->add_appointment( $appointment_obj );
|
||||
|
||||
As mentioned above, each trait provides a number of methods which are
|
||||
summarized below. For more information about each of these provided methods
|
||||
see the documentation for that specific trait.
|
||||
|
||||
Moose includes the following traits for native delegation.
|
||||
|
||||
=over 4
|
||||
|
||||
=item * L<Array|Moose::Meta::Attribute::Native::Trait::Array>
|
||||
|
||||
The following methods are provided by the native Array trait:
|
||||
|
||||
count, is_empty, elements, get, pop, push, shift, unshift, splice, first,
|
||||
first_index, grep, map, reduce, sort, sort_in_place, shuffle, uniq, join, set,
|
||||
delete, insert, clear, accessor, natatime, shallow_clone
|
||||
|
||||
=item * L<Bool|Moose::Meta::Attribute::Native::Trait::Bool>
|
||||
|
||||
The following methods are provided by the native Bool trait:
|
||||
|
||||
set, unset, toggle, not
|
||||
|
||||
=item * L<Code|Moose::Meta::Attribute::Native::Trait::Code>
|
||||
|
||||
The following methods are provided by the native Code trait:
|
||||
|
||||
execute, execute_method
|
||||
|
||||
=item * L<Counter|Moose::Meta::Attribute::Native::Trait::Counter>
|
||||
|
||||
The following methods are provided by the native Counter trait:
|
||||
|
||||
set, inc, dec, reset
|
||||
|
||||
=item * L<Hash|Moose::Meta::Attribute::Native::Trait::Hash>
|
||||
|
||||
The following methods are provided by the native Hash trait:
|
||||
|
||||
get, set, delete, keys, exists, defined, values, kv, elements, clear, count,
|
||||
is_empty, accessor, shallow_clone
|
||||
|
||||
=item * L<Number|Moose::Meta::Attribute::Native::Trait::Number>
|
||||
|
||||
The following methods are provided by the native Number trait:
|
||||
|
||||
add, sub, mul, div, mod, abs
|
||||
|
||||
=item * L<String|Moose::Meta::Attribute::Native::Trait::String>
|
||||
|
||||
The following methods are provided by the native String trait:
|
||||
|
||||
inc, append, prepend, replace, match, chop, chomp, clear, length, substr
|
||||
|
||||
=back
|
||||
|
||||
=head1 CURRYING
|
||||
|
||||
Currying allows you to create a method with some pre-set parameters. You can
|
||||
create a curried delegation method:
|
||||
|
||||
package Spider;
|
||||
use Moose;
|
||||
|
||||
has request => (
|
||||
is => 'ro'
|
||||
isa => 'HTTP::Request',
|
||||
handles => {
|
||||
set_user_agent => [ header => 'UserAgent' ],
|
||||
},
|
||||
)
|
||||
|
||||
With this definition, calling C<< $spider->set_user_agent('MyClient') >> will
|
||||
call C<< $spider->request->header('UserAgent', 'MyClient') >> behind the
|
||||
scenes.
|
||||
|
||||
Note that with currying, the currying always starts with the first parameter to
|
||||
a method (C<$_[0]>). Any arguments you pass to the delegation come after the
|
||||
curried arguments.
|
||||
|
||||
=head1 MISSING ATTRIBUTES
|
||||
|
||||
It is perfectly valid to delegate methods to an attribute which is not
|
||||
required or can be undefined. When a delegated method is called, Moose
|
||||
will throw a runtime error if the attribute does not contain an
|
||||
object.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
Stevan Little <stevan@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=item *
|
||||
|
||||
Jesse Luehrs <doy@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Shawn M Moore <sartak@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
|
||||
|
||||
=item *
|
||||
|
||||
Karen Etheridge <ether@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Florian Ragwitz <rafl@debian.org>
|
||||
|
||||
=item *
|
||||
|
||||
Hans Dieter Pearcey <hdp@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Chris Prather <chris@prather.org>
|
||||
|
||||
=item *
|
||||
|
||||
Matt S Trout <mstrout@cpan.org>
|
||||
|
||||
=back
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2006 by Infinity Interactive, Inc.
|
||||
|
||||
This is free software; you can redistribute it and/or modify it under
|
||||
the same terms as the Perl 5 programming language system itself.
|
||||
|
||||
=cut
|
||||
1275
CPAN/Moose/Manual/Delta.pod
Normal file
1275
CPAN/Moose/Manual/Delta.pod
Normal file
File diff suppressed because it is too large
Load Diff
239
CPAN/Moose/Manual/Exceptions.pod
Normal file
239
CPAN/Moose/Manual/Exceptions.pod
Normal file
@@ -0,0 +1,239 @@
|
||||
# PODNAME: Moose::Manual::Exceptions
|
||||
# ABSTRACT: Moose's exceptions
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Moose::Manual::Exceptions - Moose's exceptions
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 2.2207
|
||||
|
||||
=head1 EXCEPTIONS IN MOOSE
|
||||
|
||||
Moose will throw an exception for all error conditions. This applies both to
|
||||
code in the Moose core I<as well> as to all code generated when a class is
|
||||
made immutable. All exceptions are subclasses of the C<Moose::Exception>
|
||||
class.
|
||||
|
||||
Each type of error has its own unique subclass, and many subclasses have
|
||||
additional attributes to provide more information about the error's context,
|
||||
such as what classes or roles were involved.
|
||||
|
||||
=head1 EXCEPTION STRINGIFICATION
|
||||
|
||||
By default, Moose exceptions remove Moose internals from the stack trace. If
|
||||
you set the C<MOOSE_FULL_EXCEPTION> environment variable to a true value, then
|
||||
the Moose internals will be included in the trace.
|
||||
|
||||
=head1 HANDLING MOOSE EXCEPTIONS
|
||||
|
||||
Because Moose's exceptions use the standard C<die> mechanism, you are free to
|
||||
catch and handle errors however you like. You could use an C<eval> block to
|
||||
catch Moose exceptions. However, the Moose team strongly recommends using
|
||||
L<Try::Tiny> instead. Please refer to L<Try::Tiny>'s documentation for a
|
||||
discussion of how C<eval> is dangerous.
|
||||
|
||||
The following example demonstrates how to catch and inspect a
|
||||
L<Moose::Exception>. For the sake of simplicity, we will cause a very simple
|
||||
error. The C<extends> keywords expects a list of superclass names. If we pass
|
||||
no superclass names, Moose will throw an instance of
|
||||
L<Moose::Exception::ExtendsMissingArgs>.
|
||||
|
||||
=head2 Catching with Try::Tiny
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
use Try::Tiny;
|
||||
|
||||
try {
|
||||
package Example::Exception;
|
||||
use Moose;
|
||||
extends; # <-- error!
|
||||
}
|
||||
catch {
|
||||
# $_ contains the instance of the exception thrown by the above try
|
||||
# block, but $_ may get clobbered, so we should copy its value to
|
||||
# another variable.
|
||||
my $e = $_;
|
||||
|
||||
# Exception objects are not ubiquitous in Perl, so we must check
|
||||
# whether $e is blessed. We also need to ensure that $e is actually
|
||||
# the kind of exception we were expecting.
|
||||
if ( blessed $e
|
||||
&& $e->isa('Moose::Exception::ExtendsMissingArgs') ) {
|
||||
|
||||
my $class_name = $e->class_name;
|
||||
warn "You forgot to specify a superclass for $class_name, silly!";
|
||||
}
|
||||
|
||||
# It's either another type of an object or not an object at all.
|
||||
else {
|
||||
warn "$e\n";
|
||||
}
|
||||
};
|
||||
|
||||
=head2 Example of catching ValidationFailedForTypeConstraint
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
use Try::Tiny;
|
||||
|
||||
{
|
||||
package Person;
|
||||
use Moose;
|
||||
use Moose::Util::TypeConstraints;
|
||||
|
||||
subtype 'NameStr',
|
||||
as 'Str',
|
||||
where { $_ =~ /^[a-zA-Z]+$/; };
|
||||
|
||||
has age => (
|
||||
is => 'ro',
|
||||
isa => 'Int',
|
||||
required => 1
|
||||
);
|
||||
|
||||
has name => (
|
||||
is => 'ro',
|
||||
isa => 'NameStr',
|
||||
required => 1
|
||||
);
|
||||
}
|
||||
|
||||
my $person;
|
||||
while ( !$person ) {
|
||||
try {
|
||||
print 'Enter your age : ';
|
||||
my $age = <STDIN>;
|
||||
chomp $age;
|
||||
print 'Enter your name : ';
|
||||
my $name = <STDIN>;
|
||||
chomp $name;
|
||||
$person = Person->new(
|
||||
age => $age,
|
||||
name => $name
|
||||
);
|
||||
my $person_name = $person->name;
|
||||
my $person_age = $person->age;
|
||||
print "$person_name is $person_age years old\n";
|
||||
}
|
||||
catch {
|
||||
my $e = $_;
|
||||
|
||||
if (
|
||||
blessed $e
|
||||
&& $e->isa(
|
||||
'Moose::Exception::ValidationFailedForTypeConstraint')
|
||||
) {
|
||||
|
||||
my $attribute_name = $e->attribute->name;
|
||||
my $type_name = $e->type->name;
|
||||
my $value = $e->value;
|
||||
|
||||
warn
|
||||
"You entered $value for $attribute_name, which is not a $type_name!";
|
||||
}
|
||||
else {
|
||||
warn "$e\n";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
=head2 Example of catching AttributeIsRequired
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
use Try::Tiny;
|
||||
|
||||
{
|
||||
package Example::RequiredAttribute;
|
||||
use Moose;
|
||||
|
||||
has required_attribute => (
|
||||
is => 'ro',
|
||||
isa => 'Int',
|
||||
required => 1
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
# we're not passing required_attribute, so it'll throw an exception
|
||||
my $object = Example::RequiredAttribute->new();
|
||||
}
|
||||
catch {
|
||||
my $e = $_;
|
||||
if ( blessed $e && $e->isa('Moose::Exception::AttributeIsRequired') )
|
||||
{
|
||||
warn $e->message, "\n";
|
||||
}
|
||||
else {
|
||||
warn "$e\n";
|
||||
}
|
||||
};
|
||||
|
||||
=head1 MOOSE EXCEPTION CLASSES
|
||||
|
||||
All the exception classes are listed in L<Moose::Manual::Exceptions::Manifest>.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
Stevan Little <stevan@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=item *
|
||||
|
||||
Jesse Luehrs <doy@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Shawn M Moore <sartak@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
|
||||
|
||||
=item *
|
||||
|
||||
Karen Etheridge <ether@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Florian Ragwitz <rafl@debian.org>
|
||||
|
||||
=item *
|
||||
|
||||
Hans Dieter Pearcey <hdp@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Chris Prather <chris@prather.org>
|
||||
|
||||
=item *
|
||||
|
||||
Matt S Trout <mstrout@cpan.org>
|
||||
|
||||
=back
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2006 by Infinity Interactive, Inc.
|
||||
|
||||
This is free software; you can redistribute it and/or modify it under
|
||||
the same terms as the Perl 5 programming language system itself.
|
||||
|
||||
=cut
|
||||
4124
CPAN/Moose/Manual/Exceptions/Manifest.pod
Normal file
4124
CPAN/Moose/Manual/Exceptions/Manifest.pod
Normal file
File diff suppressed because it is too large
Load Diff
470
CPAN/Moose/Manual/FAQ.pod
Normal file
470
CPAN/Moose/Manual/FAQ.pod
Normal file
@@ -0,0 +1,470 @@
|
||||
# PODNAME: Moose::Manual::FAQ
|
||||
# ABSTRACT: Frequently asked questions about Moose
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Moose::Manual::FAQ - Frequently asked questions about Moose
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 2.2207
|
||||
|
||||
=head1 FREQUENTLY ASKED QUESTIONS
|
||||
|
||||
=head2 Module Stability
|
||||
|
||||
=head3 Is Moose "production ready"?
|
||||
|
||||
Yes! Many sites with household names are using Moose to build
|
||||
high-traffic services. Countless others are using Moose in production.
|
||||
See L<http://moose.iinteractive.com/about.html#organizations> for
|
||||
a partial list.
|
||||
|
||||
As of this writing, Moose is a dependency of several hundred CPAN
|
||||
modules. L<https://metacpan.org/requires/module/Moose>
|
||||
|
||||
=head3 Is Moose's API stable?
|
||||
|
||||
Yes. The sugary API, the one 95% of users will interact with, is
|
||||
B<very stable>. Any changes will be B<100% backwards compatible>.
|
||||
|
||||
The meta API is less set in stone. We reserve the right to tweak
|
||||
parts of it to improve efficiency or consistency. This will not be
|
||||
done lightly. We do perform deprecation cycles. We I<really>
|
||||
do not like making ourselves look bad by breaking your code.
|
||||
Submitting test cases is the best way to ensure that your code is not
|
||||
inadvertently broken by refactoring.
|
||||
|
||||
=head3 I heard Moose is slow, is this true?
|
||||
|
||||
Again, this one is tricky, so Yes I<and> No.
|
||||
|
||||
Firstly, I<nothing> in life is free, and some Moose features do cost
|
||||
more than others. It is also the policy of Moose to B<only charge you
|
||||
for the features you use>, and to do our absolute best to not place
|
||||
any extra burdens on the execution of your code for features you are
|
||||
not using. Of course using Moose itself does involve some overhead,
|
||||
but it is mostly compile time. At this point we do have some options
|
||||
available for getting the speed you need.
|
||||
|
||||
Currently we provide the option of making your classes immutable as a
|
||||
means of boosting speed. This will mean a slightly larger compile time
|
||||
cost, but the runtime speed increase (especially in object
|
||||
construction) is pretty significant. This can be done with the
|
||||
following code:
|
||||
|
||||
MyClass->meta->make_immutable();
|
||||
|
||||
=head2 Constructors
|
||||
|
||||
=head3 How do I write custom constructors with Moose?
|
||||
|
||||
Ideally, you should never write your own C<new> method, and should use
|
||||
Moose's other features to handle your specific object construction
|
||||
needs. Here are a few scenarios, and the Moose way to solve them;
|
||||
|
||||
If you need to call initialization code post instance construction,
|
||||
then use the C<BUILD> method. This feature is taken directly from Perl
|
||||
6. Every C<BUILD> method in your inheritance chain is called (in the
|
||||
correct order) immediately after the instance is constructed. This
|
||||
allows you to ensure that all your superclasses are initialized
|
||||
properly as well. This is the best approach to take (when possible)
|
||||
because it makes subclassing your class much easier.
|
||||
|
||||
If you need to affect the constructor's parameters prior to the
|
||||
instance actually being constructed, you have a number of options.
|
||||
|
||||
To change the parameter processing as a whole, you can use the
|
||||
C<BUILDARGS> method. The default implementation accepts key/value
|
||||
pairs or a hash reference. You can override it to take positional
|
||||
args, or any other format
|
||||
|
||||
To change the handling of individual parameters, there are I<coercions> (See
|
||||
the L<Moose::Cookbook::Basics::HTTP_SubtypesAndCoercion> for a complete
|
||||
example and explanation of coercions). With coercions it is possible to morph
|
||||
argument values into the correct expected types. This approach is the most
|
||||
flexible and robust, but does have a slightly higher learning curve.
|
||||
|
||||
=head3 How do I make non-Moose constructors work with Moose?
|
||||
|
||||
Usually the correct approach to subclassing a non-Moose class is
|
||||
delegation. Moose makes this easy using the C<handles> keyword,
|
||||
coercions, and C<lazy_build>, so subclassing is often not the ideal
|
||||
route.
|
||||
|
||||
That said, if you really need to inherit from a non-Moose class, see
|
||||
L<Moose::Cookbook::Basics::DateTime_ExtendingNonMooseParent> for an example of how to do it,
|
||||
or take a look at L<Moose::Manual::MooseX/"MooseX::NonMoose">.
|
||||
|
||||
=head2 Accessors
|
||||
|
||||
=head3 How do I tell Moose to use get/set accessors?
|
||||
|
||||
The easiest way to accomplish this is to use the C<reader> and
|
||||
C<writer> attribute options:
|
||||
|
||||
has 'bar' => (
|
||||
isa => 'Baz',
|
||||
reader => 'get_bar',
|
||||
writer => 'set_bar',
|
||||
);
|
||||
|
||||
Moose will still take advantage of type constraints, triggers, etc.
|
||||
when creating these methods.
|
||||
|
||||
If you do not like this much typing, and wish it to be a default for
|
||||
your classes, please see L<MooseX::FollowPBP>. This extension will
|
||||
allow you to write:
|
||||
|
||||
has 'bar' => (
|
||||
isa => 'Baz',
|
||||
is => 'rw',
|
||||
);
|
||||
|
||||
Moose will create separate C<get_bar> and C<set_bar> methods instead
|
||||
of a single C<bar> method.
|
||||
|
||||
If you like C<bar> and C<set_bar>, see
|
||||
L<MooseX::SemiAffordanceAccessor>.
|
||||
|
||||
NOTE: This B<cannot> be set globally in Moose, as that would break
|
||||
other classes which are built with Moose. You can still save on typing
|
||||
by defining a new C<MyApp::Moose> that exports Moose's sugar and then
|
||||
turns on L<MooseX::FollowPBP>. See
|
||||
L<Moose::Cookbook::Extending::Mooseish_MooseSugar>.
|
||||
|
||||
=head3 How can I inflate/deflate values in accessors?
|
||||
|
||||
Well, the first question to ask is if you actually need both inflate
|
||||
and deflate.
|
||||
|
||||
If you only need to inflate, then we suggest using coercions. Here is
|
||||
some basic sample code for inflating a L<DateTime> object:
|
||||
|
||||
class_type 'DateTime';
|
||||
|
||||
coerce 'DateTime'
|
||||
=> from 'Str'
|
||||
=> via { DateTime::Format::MySQL->parse_datetime($_) };
|
||||
|
||||
has 'timestamp' => (is => 'rw', isa => 'DateTime', coerce => 1);
|
||||
|
||||
This creates a custom type for L<DateTime> objects, then attaches
|
||||
a coercion to that type. The C<timestamp> attribute is then told
|
||||
to expect a C<DateTime> type, and to try to coerce it. When a C<Str>
|
||||
type is given to the C<timestamp> accessor, it will attempt to
|
||||
coerce the value into a C<DateTime> object using the code in found
|
||||
in the C<via> block.
|
||||
|
||||
For a more comprehensive example of using coercions, see the
|
||||
L<Moose::Cookbook::Basics::HTTP_SubtypesAndCoercion>.
|
||||
|
||||
If you need to deflate your attribute's value, the current best
|
||||
practice is to add an C<around> modifier to your accessor:
|
||||
|
||||
# a timestamp which stores as
|
||||
# seconds from the epoch
|
||||
has 'timestamp' => (is => 'rw', isa => 'Int');
|
||||
|
||||
around 'timestamp' => sub {
|
||||
my $next = shift;
|
||||
my $self = shift;
|
||||
|
||||
return $self->$next unless @_;
|
||||
|
||||
# assume we get a DateTime object ...
|
||||
my $timestamp = shift;
|
||||
return $self->$next( $timestamp->epoch );
|
||||
};
|
||||
|
||||
It is also possible to do deflation using coercion, but this tends to
|
||||
get quite complex and require many subtypes. An example of this is
|
||||
outside the scope of this document, ask on #moose or send a mail to
|
||||
the list.
|
||||
|
||||
Still another option is to write a custom attribute metaclass, which
|
||||
is also outside the scope of this document, but we would be happy to
|
||||
explain it on #moose or the mailing list.
|
||||
|
||||
=head2 Method Modifiers
|
||||
|
||||
=head3 How can I affect the values in C<@_> using C<before>?
|
||||
|
||||
You can't, actually: C<before> only runs before the main method, and
|
||||
it cannot easily affect the method's execution.
|
||||
|
||||
You similarly can't use C<after> to affect the return value of a
|
||||
method.
|
||||
|
||||
We limit C<before> and C<after> because this lets you write more
|
||||
concise code. You do not have to worry about passing C<@_> to the
|
||||
original method, or forwarding its return value (being careful to
|
||||
preserve context).
|
||||
|
||||
The C<around> method modifier has neither of these limitations, but is
|
||||
a little more verbose.
|
||||
|
||||
Alternatively, the L<MooseX::Mangle> extension provides the
|
||||
C<mangle_args> function, which does allow you to affect C<@_>.
|
||||
|
||||
=head3 Can I use C<before> to stop execution of a method?
|
||||
|
||||
Yes, but only if you throw an exception. If this is too drastic a
|
||||
measure then we suggest using C<around> instead. The C<around> method
|
||||
modifier is the only modifier which can gracefully prevent execution
|
||||
of the main method. Here is an example:
|
||||
|
||||
around 'baz' => sub {
|
||||
my $next = shift;
|
||||
my ($self, %options) = @_;
|
||||
unless ($options->{bar} eq 'foo') {
|
||||
return 'bar';
|
||||
}
|
||||
$self->$next(%options);
|
||||
};
|
||||
|
||||
By choosing not to call the C<$next> method, you can stop the
|
||||
execution of the main method.
|
||||
|
||||
Alternatively, the L<MooseX::Mangle> extension provides the
|
||||
C<guard> function, which will conditionally prevent execution
|
||||
of the original method.
|
||||
|
||||
=head3 Why can't I see return values in an C<after> modifier?
|
||||
|
||||
As with the C<before> modifier, the C<after> modifier is simply called
|
||||
I<after> the main method. It is passed the original contents of C<@_>
|
||||
and B<not> the return values of the main method.
|
||||
|
||||
Again, the arguments are too lengthy as to why this has to be. And as
|
||||
with C<before> I recommend using an C<around> modifier instead. Here
|
||||
is some sample code:
|
||||
|
||||
around 'foo' => sub {
|
||||
my $next = shift;
|
||||
my ($self, @args) = @_;
|
||||
my @rv = $next->($self, @args);
|
||||
# do something silly with the return values
|
||||
return reverse @rv;
|
||||
};
|
||||
|
||||
Alternatively, the L<MooseX::Mangle> extension provides the
|
||||
C<mangle_return> function, which allows modifying the return values
|
||||
of the original method.
|
||||
|
||||
=head2 Type Constraints
|
||||
|
||||
=head3 How can I provide a custom error message for a type constraint?
|
||||
|
||||
Use the C<message> option when building the subtype:
|
||||
|
||||
subtype 'NaturalLessThanTen'
|
||||
=> as 'Natural'
|
||||
=> where { $_ < 10 }
|
||||
=> message { "This number ($_) is not less than ten!" };
|
||||
|
||||
This C<message> block will be called when a value fails to pass the
|
||||
C<NaturalLessThanTen> constraint check.
|
||||
|
||||
=head3 Can I turn off type constraint checking?
|
||||
|
||||
There's no support for it in the core of Moose yet. This option may
|
||||
come in a future release.
|
||||
|
||||
Meanwhile there's a L<MooseX
|
||||
extension|MooseX::Attribute::TypeConstraint::CustomizeFatal> that
|
||||
allows you to do this on a per-attribute basis, and if it doesn't do
|
||||
what you it's easy to write one that fits your use case.
|
||||
|
||||
=head3 My coercions stopped working with recent Moose, why did you break it?
|
||||
|
||||
Moose 0.76 fixed a case where coercions were being applied even if the original
|
||||
constraint passed. This has caused some edge cases to fail where people were
|
||||
doing something like
|
||||
|
||||
subtype 'Address', as 'Str';
|
||||
coerce 'Address', from 'Str', via { get_address($_) };
|
||||
|
||||
This is not what they intended, because the type constraint C<Address> is too
|
||||
loose in this case. It is saying that all strings are Addresses, which is
|
||||
obviously not the case. The solution is to provide a C<where> clause that
|
||||
properly restricts the type constraint:
|
||||
|
||||
subtype 'Address', as 'Str', where { looks_like_address($_) };
|
||||
|
||||
This will allow the coercion to apply only to strings that fail to look like an
|
||||
Address.
|
||||
|
||||
=head2 Roles
|
||||
|
||||
=head3 Why is BUILD not called for my composed roles?
|
||||
|
||||
C<BUILD> is never called in composed roles. The primary reason is that
|
||||
roles are B<not> order sensitive. Roles are composed in such a way
|
||||
that the order of composition does not matter (for information on the
|
||||
deeper theory of this read the original traits papers here
|
||||
L<http://www.iam.unibe.ch/~scg/Research/Traits/>).
|
||||
|
||||
Because roles are essentially unordered, it would be impossible to
|
||||
determine the order in which to execute the C<BUILD> methods.
|
||||
|
||||
As for alternate solutions, there are a couple.
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
Using a combination of lazy and default in your attributes to defer
|
||||
initialization (see the Binary Tree example in the cookbook for a good example
|
||||
of lazy/default usage
|
||||
L<Moose::Cookbook::Basics::BinaryTree_AttributeFeatures>)
|
||||
|
||||
=item *
|
||||
|
||||
Use attribute triggers, which fire after an attribute is set, to
|
||||
facilitate initialization. These are described in the L<Moose> docs,
|
||||
and examples can be found in the test suite.
|
||||
|
||||
=back
|
||||
|
||||
In general, roles should not I<require> initialization; they should
|
||||
either provide sane defaults or should be documented as needing
|
||||
specific initialization. One such way to "document" this is to have a
|
||||
separate attribute initializer which is required for the role. Here is
|
||||
an example of how to do this:
|
||||
|
||||
package My::Role;
|
||||
use Moose::Role;
|
||||
|
||||
has 'height' => (
|
||||
is => 'rw',
|
||||
isa => 'Int',
|
||||
lazy => 1,
|
||||
default => sub {
|
||||
my $self = shift;
|
||||
$self->init_height;
|
||||
}
|
||||
);
|
||||
|
||||
requires 'init_height';
|
||||
|
||||
In this example, the role will not compose successfully unless the
|
||||
class provides a C<init_height> method.
|
||||
|
||||
If none of those solutions work, then it is possible that a role is
|
||||
not the best tool for the job, and you really should be using
|
||||
classes. Or, at the very least, you should reduce the amount of
|
||||
functionality in your role so that it does not require initialization.
|
||||
|
||||
=head3 What are traits, and how are they different from roles?
|
||||
|
||||
In Moose, a trait is almost exactly the same thing as a role, except
|
||||
that traits typically register themselves, which allows you to refer
|
||||
to them by a short name ("Big" vs "MyApp::Role::Big").
|
||||
|
||||
In Moose-speak, a I<Role> is usually composed into a I<class> at
|
||||
compile time, whereas a I<Trait> is usually composed into an instance
|
||||
of a class at runtime to add or modify the behavior of B<just that
|
||||
instance>.
|
||||
|
||||
Outside the context of Moose, traits and roles generally mean exactly
|
||||
the same thing. The original paper called them traits, but Perl 6
|
||||
will call them roles.
|
||||
|
||||
=head3 Can an attribute-generated method (e.g. an accessor) satisfy requires?
|
||||
|
||||
Yes, just be sure to consume the role I<after> declaring your
|
||||
attribute. L<Moose::Manual::Roles/Required Attributes> provides
|
||||
an example:
|
||||
|
||||
package Breakable;
|
||||
use Moose::Role;
|
||||
requires 'stress';
|
||||
|
||||
package Car;
|
||||
use Moose;
|
||||
has 'stress' => ( is => 'rw', isa => 'Int' );
|
||||
with 'Breakable';
|
||||
|
||||
If you mistakenly consume the C<Breakable> role before declaring your
|
||||
C<stress> attribute, you would see an error like this:
|
||||
|
||||
'Breakable' requires the method 'stress' to be implemented by 'Car' at...
|
||||
|
||||
=head2 Moose and Subroutine Attributes
|
||||
|
||||
=head3 Why don't subroutine attributes I inherited from a superclass work?
|
||||
|
||||
Currently when subclassing a module is done at runtime with the
|
||||
C<extends> keyword, but attributes are checked at compile time by
|
||||
Perl. To make attributes work, you must place C<extends> in a C<BEGIN>
|
||||
block so that the attribute handlers will be available at compile time,
|
||||
like this:
|
||||
|
||||
BEGIN { extends qw/Foo/ }
|
||||
|
||||
Note that we're talking about Perl's subroutine attributes here, not
|
||||
Moose attributes:
|
||||
|
||||
sub foo : Bar(27) { ... }
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
Stevan Little <stevan@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=item *
|
||||
|
||||
Jesse Luehrs <doy@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Shawn M Moore <sartak@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
|
||||
|
||||
=item *
|
||||
|
||||
Karen Etheridge <ether@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Florian Ragwitz <rafl@debian.org>
|
||||
|
||||
=item *
|
||||
|
||||
Hans Dieter Pearcey <hdp@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Chris Prather <chris@prather.org>
|
||||
|
||||
=item *
|
||||
|
||||
Matt S Trout <mstrout@cpan.org>
|
||||
|
||||
=back
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2006 by Infinity Interactive, Inc.
|
||||
|
||||
This is free software; you can redistribute it and/or modify it under
|
||||
the same terms as the Perl 5 programming language system itself.
|
||||
|
||||
=cut
|
||||
214
CPAN/Moose/Manual/MOP.pod
Normal file
214
CPAN/Moose/Manual/MOP.pod
Normal file
@@ -0,0 +1,214 @@
|
||||
# PODNAME: Moose::Manual::MOP
|
||||
# ABSTRACT: The Moose (and Class::MOP) meta API
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Moose::Manual::MOP - The Moose (and Class::MOP) meta API
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 2.2207
|
||||
|
||||
=head1 INTRODUCTION
|
||||
|
||||
Moose provides a powerful introspection API built on top of
|
||||
C<Class::MOP>. "MOP" stands for Meta-Object Protocol. In plainer
|
||||
English, a MOP is an API for performing introspection on classes,
|
||||
attributes, methods, and so on.
|
||||
|
||||
In fact, it is C<Class::MOP> that provides many of Moose's core
|
||||
features, including attributes, before/after/around method modifiers,
|
||||
and immutability. In most cases, Moose takes an existing C<Class::MOP>
|
||||
class and subclasses it to add additional features. Moose also adds
|
||||
some entirely new features of its own, such as roles, the augment
|
||||
modifier, and types.
|
||||
|
||||
If you're interested in the MOP, it's important to know about
|
||||
C<Class::MOP> so you know what docs to read. Often, the introspection
|
||||
method that you're looking for is defined in a C<Class::MOP> class,
|
||||
rather than Moose itself.
|
||||
|
||||
The MOP provides more than just I<read-only> introspection. It also
|
||||
lets you add attributes and methods, apply roles, and much more. In
|
||||
fact, all of the declarative Moose sugar is simply a thin layer on top
|
||||
of the MOP API.
|
||||
|
||||
If you want to write Moose extensions, you'll need to learn some of
|
||||
the MOP API. The introspection methods are also handy if you want to
|
||||
generate docs or inheritance graphs, or do some other runtime
|
||||
reflection.
|
||||
|
||||
This document is not a complete reference for the meta API. We're just
|
||||
going to cover some of the highlights, and give you a sense of how it
|
||||
all works. To really understand it, you'll have to read a lot of other
|
||||
docs, and possibly even dig into the Moose guts a bit.
|
||||
|
||||
=head1 GETTING STARTED
|
||||
|
||||
The usual entry point to the meta API is through a class's metaclass
|
||||
object, which is a L<Moose::Meta::Class>. This is available by calling
|
||||
the C<meta> method on a class or object:
|
||||
|
||||
package User;
|
||||
|
||||
use Moose;
|
||||
|
||||
my $meta = __PACKAGE__->meta;
|
||||
|
||||
The C<meta> method is added to a class when it uses Moose.
|
||||
|
||||
You can also use C<< Class::MOP::Class->initialize($name) >> to get a
|
||||
metaclass object for any class. This is safer than calling C<<
|
||||
$class->meta >> when you're not sure that the class has a meta method.
|
||||
|
||||
The C<< Class::MOP::Class->initialize >> constructor will return an
|
||||
existing metaclass if one has already been created (via Moose or some
|
||||
other means). If it hasn't, it will return a new C<Class::MOP::Class>
|
||||
object. This will work for classes that use Moose, meta API classes,
|
||||
and classes which don't use Moose at all.
|
||||
|
||||
=head1 USING THE METACLASS OBJECT
|
||||
|
||||
The metaclass object can tell you about a class's attributes, methods,
|
||||
roles, parents, and more. For example, to look at all of the class's
|
||||
attributes:
|
||||
|
||||
for my $attr ( $meta->get_all_attributes ) {
|
||||
print $attr->name, "\n";
|
||||
}
|
||||
|
||||
The C<get_all_attributes> method is documented in
|
||||
C<Class::MOP::Class>. For Moose-using classes, it returns a list of
|
||||
L<Moose::Meta::Attribute> objects for attributes defined in the class
|
||||
and its parents.
|
||||
|
||||
You can also get a list of methods:
|
||||
|
||||
for my $method ( $meta->get_all_methods ) {
|
||||
print $method->fully_qualified_name, "\n";
|
||||
}
|
||||
|
||||
Now we're looping over a list of L<Moose::Meta::Method> objects. Note
|
||||
that some of these objects may actually be a subclass of
|
||||
L<Moose::Meta::Method>, as Moose uses different classes to represent
|
||||
wrapped methods, delegation methods, constructors, etc.
|
||||
|
||||
We can look at a class's parent classes and subclasses:
|
||||
|
||||
for my $class ( $meta->linearized_isa ) {
|
||||
print "$class\n";
|
||||
}
|
||||
|
||||
for my $subclass ( $meta->subclasses ) {
|
||||
print "$subclass\n";
|
||||
}
|
||||
|
||||
Note that both these methods return class I<names>, not metaclass
|
||||
objects.
|
||||
|
||||
=head1 ALTERING CLASSES WITH THE MOP
|
||||
|
||||
The metaclass object can change the class directly, by adding
|
||||
attributes, methods, etc.
|
||||
|
||||
As an example, we can add a method to a class:
|
||||
|
||||
$meta->add_method( 'say' => sub { print @_, "\n" } );
|
||||
|
||||
Or an attribute:
|
||||
|
||||
$meta->add_attribute( 'size' => ( is => 'rw', isa => 'Int' ) );
|
||||
|
||||
Obviously, this is much more cumbersome than using Perl syntax or
|
||||
Moose sugar for defining methods and attributes, but this API allows
|
||||
for very powerful extensions.
|
||||
|
||||
You might remember that we've talked about making classes immutable
|
||||
elsewhere in the manual. This is a good practice. However, once a
|
||||
class is immutable, calling any of these update methods will throw an
|
||||
exception.
|
||||
|
||||
You can make a class mutable again simply by calling C<<
|
||||
$meta->make_mutable >>. Once you're done changing it, you can
|
||||
restore immutability by calling C<< $meta->make_immutable >>.
|
||||
|
||||
However, the most common use for this part of the meta API is as
|
||||
part of Moose extensions. These extensions should assume that they are
|
||||
being run before you make a class immutable.
|
||||
|
||||
=head1 GOING FURTHER
|
||||
|
||||
If you're interested in extending Moose, we recommend reading all of
|
||||
the "Meta" and "Extending" recipes in the L<Moose::Cookbook>. Those
|
||||
recipes show various practical applications of the MOP.
|
||||
|
||||
If you'd like to write your own extensions, one of the best ways to
|
||||
learn more about this is to look at other similar extensions to see
|
||||
how they work. You'll probably also need to read various API docs,
|
||||
including the docs for the various C<Moose::Meta::*> and
|
||||
C<Class::MOP::*> classes.
|
||||
|
||||
Finally, we welcome questions on the Moose mailing list and
|
||||
IRC. Information on the mailing list, IRC, and more references can be
|
||||
found in the L<Moose.pm docs|Moose/GETTING HELP>.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
Stevan Little <stevan@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=item *
|
||||
|
||||
Jesse Luehrs <doy@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Shawn M Moore <sartak@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
|
||||
|
||||
=item *
|
||||
|
||||
Karen Etheridge <ether@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Florian Ragwitz <rafl@debian.org>
|
||||
|
||||
=item *
|
||||
|
||||
Hans Dieter Pearcey <hdp@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Chris Prather <chris@prather.org>
|
||||
|
||||
=item *
|
||||
|
||||
Matt S Trout <mstrout@cpan.org>
|
||||
|
||||
=back
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2006 by Infinity Interactive, Inc.
|
||||
|
||||
This is free software; you can redistribute it and/or modify it under
|
||||
the same terms as the Perl 5 programming language system itself.
|
||||
|
||||
=cut
|
||||
449
CPAN/Moose/Manual/MethodModifiers.pod
Normal file
449
CPAN/Moose/Manual/MethodModifiers.pod
Normal file
@@ -0,0 +1,449 @@
|
||||
# PODNAME: Moose::Manual::MethodModifiers
|
||||
# ABSTRACT: Moose's method modifiers
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Moose::Manual::MethodModifiers - Moose's method modifiers
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 2.2207
|
||||
|
||||
=head1 WHAT IS A METHOD MODIFIER?
|
||||
|
||||
Moose provides a feature called "method modifiers". You can also think
|
||||
of these as "hooks" or "advice".
|
||||
|
||||
It's probably easiest to understand this feature with a few examples:
|
||||
|
||||
package Example;
|
||||
|
||||
use Moose;
|
||||
|
||||
sub foo {
|
||||
print " foo\n";
|
||||
}
|
||||
|
||||
before 'foo' => sub { print "about to call foo\n"; };
|
||||
after 'foo' => sub { print "just called foo\n"; };
|
||||
|
||||
around 'foo' => sub {
|
||||
my $orig = shift;
|
||||
my $self = shift;
|
||||
|
||||
print " I'm around foo\n";
|
||||
|
||||
$self->$orig(@_);
|
||||
|
||||
print " I'm still around foo\n";
|
||||
};
|
||||
|
||||
Now if I call C<< Example->new->foo >> I'll get the following output:
|
||||
|
||||
about to call foo
|
||||
I'm around foo
|
||||
foo
|
||||
I'm still around foo
|
||||
just called foo
|
||||
|
||||
You probably could have figured that out from the names "before",
|
||||
"after", and "around".
|
||||
|
||||
Also, as you can see, the before modifiers come before around
|
||||
modifiers, and after modifiers come last.
|
||||
|
||||
When there are multiple modifiers of the same type, the before and
|
||||
around modifiers run from the last added to the first, and after
|
||||
modifiers run from first added to last:
|
||||
|
||||
before 2
|
||||
before 1
|
||||
around 2
|
||||
around 1
|
||||
primary
|
||||
around 1
|
||||
around 2
|
||||
after 1
|
||||
after 2
|
||||
|
||||
=head1 WHY USE THEM?
|
||||
|
||||
Method modifiers have many uses. They are often used in roles to alter the
|
||||
behavior of methods in the classes that consume the role. See
|
||||
L<Moose::Manual::Roles> for more information about roles.
|
||||
|
||||
Since modifiers are mostly useful in roles, some of the examples below
|
||||
are a bit artificial. They're intended to give you an idea of how
|
||||
modifiers work, but may not be the most natural usage.
|
||||
|
||||
=head1 BEFORE, AFTER, AND AROUND
|
||||
|
||||
Method modifiers can be used to add behavior to methods without modifying the definition of those methods.
|
||||
|
||||
=head2 Before and after Modifiers
|
||||
|
||||
Method modifiers can be used to add behavior to a method that Moose
|
||||
generates for you, such as an attribute accessor:
|
||||
|
||||
has 'size' => ( is => 'rw' );
|
||||
|
||||
before 'size' => sub {
|
||||
my $self = shift;
|
||||
|
||||
if (@_) {
|
||||
Carp::cluck('Someone is setting size');
|
||||
}
|
||||
};
|
||||
|
||||
Another use for the before modifier would be to do some sort of
|
||||
prechecking on a method call. For example:
|
||||
|
||||
before 'size' => sub {
|
||||
my $self = shift;
|
||||
|
||||
die 'Cannot set size while the person is growing'
|
||||
if @_ && $self->is_growing;
|
||||
};
|
||||
|
||||
This lets us implement logical checks that don't make sense as type
|
||||
constraints. In particular, they're useful for defining logical rules
|
||||
about an object's state changes.
|
||||
|
||||
Similarly, an after modifier could be used for logging an action that
|
||||
was taken.
|
||||
|
||||
Note that the return values of both before and after modifiers are
|
||||
ignored.
|
||||
|
||||
=head2 Around modifiers
|
||||
|
||||
An around modifier is more powerful than either a before or
|
||||
after modifier. It can modify the arguments being passed to the
|
||||
original method, and you can even decide to simply not call the
|
||||
original method at all. You can also modify the return value with an
|
||||
around modifier.
|
||||
|
||||
An around modifier receives the original method as its first argument,
|
||||
I<then> the object, and finally any arguments passed to the method.
|
||||
|
||||
around 'size' => sub {
|
||||
my $orig = shift;
|
||||
my $self = shift;
|
||||
|
||||
return $self->$orig()
|
||||
unless @_;
|
||||
|
||||
my $size = shift;
|
||||
$size = $size / 2
|
||||
if $self->likes_small_things();
|
||||
|
||||
return $self->$orig($size);
|
||||
};
|
||||
|
||||
=head2 Wrapping multiple methods at once
|
||||
|
||||
C<before>, C<after>, and C<around> can also modify multiple methods
|
||||
at once. The simplest example of this is passing them as a list:
|
||||
|
||||
before [qw(foo bar baz)] => sub {
|
||||
warn "something is being called!";
|
||||
};
|
||||
|
||||
This will add a C<before> modifier to each of the C<foo>, C<bar>,
|
||||
and C<baz> methods in the current class, just as though a separate
|
||||
call to C<before> was made for each of them. The list can be passed
|
||||
either as a bare list, or as an arrayref. Note that the name of the
|
||||
function being modified isn't passed in in any way; this syntax is
|
||||
only intended for cases where the function being modified doesn't
|
||||
actually matter. If the function name does matter, use something like this:
|
||||
|
||||
for my $func (qw(foo bar baz)) {
|
||||
before $func => sub {
|
||||
warn "$func was called!";
|
||||
};
|
||||
}
|
||||
|
||||
=head2 Using regular expressions to select methods to wrap
|
||||
|
||||
In addition, you can specify a regular expression to indicate the
|
||||
methods to wrap, like so:
|
||||
|
||||
after qr/^command_/ => sub {
|
||||
warn "got a command";
|
||||
};
|
||||
|
||||
This will match the regular expression against each method name
|
||||
returned by L<Class::MOP::Class/get_method_list>, and add a modifier
|
||||
to each one that matches. The same caveats apply as above.
|
||||
|
||||
Using regular expressions to determine methods to wrap is quite a bit more
|
||||
powerful than the previous alternatives, but it's also quite a bit more
|
||||
dangerous. Bear in mind that if your regular expression matches certain Perl
|
||||
and Moose reserved method names with a special meaning to Moose or Perl, such
|
||||
as C<meta>, C<new>, C<BUILD>, C<DESTROY>, C<AUTOLOAD>, etc, this could cause
|
||||
unintended (and hard to debug) problems and is best avoided.
|
||||
|
||||
=head2 Execution order of method modifiers and inheritance
|
||||
|
||||
When both a superclass and an inheriting class have the same method modifiers,
|
||||
the method modifiers of the inheriting class are wrapped around the method
|
||||
modifiers of the superclass, as the following example illustrates:
|
||||
|
||||
Here is the parent class:
|
||||
|
||||
package Superclass;
|
||||
use Moose;
|
||||
sub rant { printf " RANTING!\n" }
|
||||
before 'rant' => sub { printf " In %s before\n", __PACKAGE__ };
|
||||
after 'rant' => sub { printf " In %s after\n", __PACKAGE__ };
|
||||
around 'rant' => sub {
|
||||
my $orig = shift;
|
||||
my $self = shift;
|
||||
printf " In %s around before calling original\n", __PACKAGE__;
|
||||
$self->$orig;
|
||||
printf " In %s around after calling original\n", __PACKAGE__;
|
||||
};
|
||||
1;
|
||||
|
||||
And the child class:
|
||||
|
||||
package Subclass;
|
||||
use Moose;
|
||||
extends 'Superclass';
|
||||
before 'rant' => sub { printf "In %s before\n", __PACKAGE__ };
|
||||
after 'rant' => sub { printf "In %s after\n", __PACKAGE__ };
|
||||
around 'rant' => sub {
|
||||
my $orig = shift;
|
||||
my $self = shift;
|
||||
printf " In %s around before calling original\n", __PACKAGE__;
|
||||
$self->$orig;
|
||||
printf " In %s around after calling original\n", __PACKAGE__;
|
||||
};
|
||||
1;
|
||||
|
||||
And here's the output when we call the wrapped method (C<< Child->rant >>):
|
||||
|
||||
% perl -MSubclass -e 'Subclass->new->rant'
|
||||
|
||||
In Subclass before
|
||||
In Subclass around before calling original
|
||||
In Superclass before
|
||||
In Superclass around before calling original
|
||||
RANTING!
|
||||
In Superclass around after calling original
|
||||
In Superclass after
|
||||
In Subclass around after calling original
|
||||
In Subclass after
|
||||
|
||||
=head1 INNER AND AUGMENT
|
||||
|
||||
Augment and inner are two halves of the same feature. The augment
|
||||
modifier provides a sort of inverted subclassing. You provide part of
|
||||
the implementation in a superclass, and then document that subclasses
|
||||
are expected to provide the rest.
|
||||
|
||||
The superclass calls C<inner()>, which then calls the C<augment>
|
||||
modifier in the subclass:
|
||||
|
||||
package Document;
|
||||
|
||||
use Moose;
|
||||
|
||||
sub as_xml {
|
||||
my $self = shift;
|
||||
|
||||
my $xml = "<document>\n";
|
||||
$xml .= inner();
|
||||
$xml .= "</document>\n";
|
||||
|
||||
return $xml;
|
||||
}
|
||||
|
||||
Using C<inner()> in this method makes it possible for one or more
|
||||
subclasses to then augment this method with their own specific
|
||||
implementation:
|
||||
|
||||
package Report;
|
||||
|
||||
use Moose;
|
||||
|
||||
extends 'Document';
|
||||
|
||||
augment 'as_xml' => sub {
|
||||
my $self = shift;
|
||||
|
||||
my $xml = " <report>\n";
|
||||
$xml .= inner();
|
||||
$xml .= " </report>\n";
|
||||
|
||||
return $xml;
|
||||
};
|
||||
|
||||
When we call C<as_xml> on a Report object, we get something like this:
|
||||
|
||||
<document>
|
||||
<report>
|
||||
</report>
|
||||
</document>
|
||||
|
||||
But we also called C<inner()> in C<Report>, so we can continue
|
||||
subclassing and adding more content inside the document:
|
||||
|
||||
package Report::IncomeAndExpenses;
|
||||
|
||||
use Moose;
|
||||
|
||||
extends 'Report';
|
||||
|
||||
augment 'as_xml' => sub {
|
||||
my $self = shift;
|
||||
|
||||
my $xml = ' <income>' . $self->income . '</income>';
|
||||
$xml .= "\n";
|
||||
$xml .= ' <expenses>' . $self->expenses . '</expenses>';
|
||||
$xml .= "\n";
|
||||
|
||||
$xml .= inner() || q{};
|
||||
|
||||
return $xml;
|
||||
};
|
||||
|
||||
Now our report has some content:
|
||||
|
||||
<document>
|
||||
<report>
|
||||
<income>$10</income>
|
||||
<expenses>$8</expenses>
|
||||
</report>
|
||||
</document>
|
||||
|
||||
What makes this combination of C<augment> and C<inner()> special is
|
||||
that it allows us to have methods which are called from parent (least
|
||||
specific) to child (most specific). This inverts the normal
|
||||
inheritance pattern.
|
||||
|
||||
Note that in C<Report::IncomeAndExpenses> we call C<inner()> again. If the
|
||||
object is an instance of C<Report::IncomeAndExpenses> then this call is a
|
||||
no-op, and just returns false. It's a good idea to always call C<inner()> to
|
||||
allow for future subclassing.
|
||||
|
||||
=head1 OVERRIDE AND SUPER
|
||||
|
||||
Finally, Moose provides some simple sugar for Perl's built-in method
|
||||
overriding scheme. If you want to override a method from a parent
|
||||
class, you can do this with C<override>:
|
||||
|
||||
package Employee;
|
||||
|
||||
use Moose;
|
||||
|
||||
extends 'Person';
|
||||
|
||||
has 'job_title' => ( is => 'rw' );
|
||||
|
||||
override 'display_name' => sub {
|
||||
my $self = shift;
|
||||
|
||||
return super() . q{, } . $self->job_title();
|
||||
};
|
||||
|
||||
The call to C<super()> is almost the same as calling C<<
|
||||
$self->SUPER::display_name >>. The difference is that the arguments
|
||||
passed to the superclass's method will always be the same as the ones
|
||||
passed to the method modifier, and cannot be changed.
|
||||
|
||||
All arguments passed to C<super()> are ignored, as are any changes
|
||||
made to C<@_> before C<super()> is called.
|
||||
|
||||
=head1 SEMI-COLONS
|
||||
|
||||
Because all of these method modifiers are implemented as Perl
|
||||
functions, you must always end the modifier declaration with a
|
||||
semi-colon:
|
||||
|
||||
after 'foo' => sub { };
|
||||
|
||||
=head1 EXCEPTIONS AND STACK TRACES
|
||||
|
||||
An exception thrown in a C<before> modifier will prevent the method it
|
||||
modifies from being called at all. An exception in an C<around> modifier may
|
||||
prevent the modified method from being called, depending on how the C<around>
|
||||
modifier is structured. An exception in an C<after> modifier obviously cannot
|
||||
prevent the method it wraps from being called.
|
||||
|
||||
Both C<override> and C<augment> are similar to C<around> in that they can
|
||||
decide whether or not to call the method they modify before or after throwing
|
||||
an exception.
|
||||
|
||||
From the caller's perspective, an exception in a method modifier will look
|
||||
like the method it called threw an exception. However, method modifiers are
|
||||
just standard Perl subroutines. This means that they end up on the stack in
|
||||
stack traces as an additional frame.
|
||||
|
||||
=head1 CAVEATS
|
||||
|
||||
These method modification features do not work well with multiple inheritance,
|
||||
due to how method resolution is performed in Perl. Experiment with a test
|
||||
program to ensure your class hierarchy works as expected, or more preferably,
|
||||
don't use multiple inheritance (roles can help with this)!
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
Stevan Little <stevan@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=item *
|
||||
|
||||
Jesse Luehrs <doy@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Shawn M Moore <sartak@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
|
||||
|
||||
=item *
|
||||
|
||||
Karen Etheridge <ether@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Florian Ragwitz <rafl@debian.org>
|
||||
|
||||
=item *
|
||||
|
||||
Hans Dieter Pearcey <hdp@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Chris Prather <chris@prather.org>
|
||||
|
||||
=item *
|
||||
|
||||
Matt S Trout <mstrout@cpan.org>
|
||||
|
||||
=back
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2006 by Infinity Interactive, Inc.
|
||||
|
||||
This is free software; you can redistribute it and/or modify it under
|
||||
the same terms as the Perl 5 programming language system itself.
|
||||
|
||||
=cut
|
||||
326
CPAN/Moose/Manual/MooseX.pod
Normal file
326
CPAN/Moose/Manual/MooseX.pod
Normal file
@@ -0,0 +1,326 @@
|
||||
# PODNAME: Moose::Manual::MooseX
|
||||
# ABSTRACT: Recommended Moose extensions
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Moose::Manual::MooseX - Recommended Moose extensions
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 2.2207
|
||||
|
||||
=head1 MooseX?
|
||||
|
||||
It's easy to extend and change Moose, and this is part of what makes
|
||||
Moose so powerful. You can use the MOP API to do things your own way,
|
||||
add new features, and generally customize your Moose.
|
||||
|
||||
Writing your own extensions does require a good understanding of the
|
||||
meta-model. You can start learning about this with the
|
||||
L<Moose::Manual::MOP> docs. There are also several extension recipes
|
||||
in the L<Moose::Cookbook>.
|
||||
|
||||
Explaining how to write extensions is beyond the scope of this
|
||||
manual. Fortunately, lots of people have already written extensions
|
||||
and put them on CPAN for you.
|
||||
|
||||
This document covers a few of the ones we like best.
|
||||
|
||||
=head1 L<MooseX::AttributeHelpers>
|
||||
|
||||
The functionality of this MooseX module has been moved into Moose core.
|
||||
See L<Moose::Meta::Attribute::Native>.
|
||||
|
||||
=head1 L<Moose::Autobox>
|
||||
|
||||
MooseX::AttributeHelpers, but turned inside out, Moose::Autobox provides
|
||||
methods on both arrays/hashes/etc. but also references to them, using
|
||||
Moose roles, allowing you do to things like:
|
||||
|
||||
use Moose::Autobox;
|
||||
|
||||
$somebody_elses_object->orders->push($order);
|
||||
|
||||
Lexically scoped and not to everybody's taste, but very handy for sugaring
|
||||
up other people's APIs and your own code.
|
||||
|
||||
=head1 L<MooseX::StrictConstructor>
|
||||
|
||||
By default, Moose lets you pass any old junk into a class's
|
||||
constructor. If you load L<MooseX::StrictConstructor>, your class will
|
||||
throw an error if it sees something it doesn't recognize;
|
||||
|
||||
package User;
|
||||
|
||||
use Moose;
|
||||
use MooseX::StrictConstructor;
|
||||
|
||||
has 'name';
|
||||
has 'email';
|
||||
|
||||
User->new( name => 'Bob', emali => 'bob@example.com' );
|
||||
|
||||
With L<MooseX::StrictConstructor>, that typo ("emali") will cause a
|
||||
runtime error. With plain old Moose, the "emali" attribute would be
|
||||
silently ignored.
|
||||
|
||||
=head1 L<MooseX::Params::Validate>
|
||||
|
||||
We have high hopes for the future of L<MooseX::Method::Signatures> and
|
||||
L<Moops>. However, these modules, while used regularly in
|
||||
production by some of the more insane members of the community, are
|
||||
still marked alpha just in case backwards incompatible changes need to
|
||||
be made.
|
||||
|
||||
If you don't want to risk that, for now we recommend the decidedly more
|
||||
clunky (but also faster and simpler) L<MooseX::Params::Validate>. This
|
||||
module lets you apply Moose types and coercions to any method
|
||||
arguments.
|
||||
|
||||
package User;
|
||||
|
||||
use Moose;
|
||||
use MooseX::Params::Validate;
|
||||
|
||||
sub login {
|
||||
my $self = shift;
|
||||
my ($password)
|
||||
= validated_list( \@_, password => { isa => 'Str', required => 1 } );
|
||||
|
||||
...
|
||||
}
|
||||
|
||||
=head1 L<MooseX::Getopt>
|
||||
|
||||
This is a role which adds a C<new_with_options> method to your
|
||||
class. This is a constructor that takes the command line options and
|
||||
uses them to populate attributes.
|
||||
|
||||
This makes writing a command-line application as a module trivially
|
||||
simple:
|
||||
|
||||
package App::Foo;
|
||||
|
||||
use Moose;
|
||||
with 'MooseX::Getopt';
|
||||
|
||||
has 'input' => (
|
||||
is => 'ro',
|
||||
isa => 'Str',
|
||||
required => 1
|
||||
);
|
||||
|
||||
has 'output' => (
|
||||
is => 'ro',
|
||||
isa => 'Str',
|
||||
required => 1
|
||||
);
|
||||
|
||||
sub run { ... }
|
||||
|
||||
Then in the script that gets run we have:
|
||||
|
||||
use App::Foo;
|
||||
|
||||
App::Foo->new_with_options->run;
|
||||
|
||||
From the command line, someone can execute the script:
|
||||
|
||||
foo@example> foo --input /path/to/input --output /path/to/output
|
||||
|
||||
=head1 L<MooseX::Singleton>
|
||||
|
||||
To be honest, using a singleton is just a way to have a magic global
|
||||
variable in languages that don't actually have global variables.
|
||||
|
||||
In perl, you can just as easily use a global. However, if your
|
||||
colleagues are Java-infected, they might prefer a singleton. Also, if
|
||||
you have an existing class that I<isn't> a singleton but should be,
|
||||
using L<MooseX::Singleton> is the easiest way to convert it.
|
||||
|
||||
package Config;
|
||||
|
||||
use MooseX::Singleton; # instead of Moose
|
||||
|
||||
has 'cache_dir' => ( ... );
|
||||
|
||||
It's that simple.
|
||||
|
||||
=head1 EXTENSIONS TO CONSIDER
|
||||
|
||||
There are literally dozens of other extensions on CPAN. This is a list
|
||||
of extensions that you might find useful, but we're not quite ready to
|
||||
endorse just yet.
|
||||
|
||||
=head2 L<MooseX::Declare>
|
||||
|
||||
MooseX::Declare is based on L<Devel::Declare>, a giant bag of crack
|
||||
originally implemented by mst with the goal of upsetting the perl core
|
||||
developers so much by its very existence that they implemented proper
|
||||
keyword handling in the core.
|
||||
|
||||
As of perl5 version 14, this goal has been achieved, and modules such
|
||||
as L<Devel::CallParser>, L<Function::Parameters>, and L<Keyword::Simple> provide
|
||||
mechanisms to mangle perl syntax that don't require hallucinogenic
|
||||
drugs to interpret the error messages they produce.
|
||||
|
||||
If you want to use declarative syntax in new code, please for the love
|
||||
of kittens get yourself a recent perl and look at L<Moops> instead.
|
||||
|
||||
=head2 L<MooseX::Types>
|
||||
|
||||
This extension helps you build a type library for your application. It
|
||||
also lets you predeclare type names and use them as barewords.
|
||||
|
||||
use MooseX::Types -declare => ['PositiveInt'];
|
||||
use MooseX::Types::Moose 'Int';
|
||||
|
||||
subtype PositiveInt,
|
||||
as Int,
|
||||
where { $_ > 0 },
|
||||
message { "Int is not larger than 0" };
|
||||
|
||||
One nice feature is that those bareword names are actually namespaced
|
||||
in Moose's type registry, so multiple applications can use the same
|
||||
bareword names, even if the type definitions differ.
|
||||
|
||||
=head2 L<MooseX::Types::Structured>
|
||||
|
||||
This extension builds on top of L<MooseX::Types> to let you declare
|
||||
complex data structure types.
|
||||
|
||||
use MooseX::Types -declare => [ qw( Name Color ) ];
|
||||
use MooseX::Types::Moose qw(Str Int);
|
||||
use MooseX::Types::Structured qw(Dict Tuple Optional);
|
||||
|
||||
subtype Name
|
||||
=> as Dict[ first => Str, middle => Optional[Str], last => Str ];
|
||||
|
||||
subtype Color
|
||||
=> as Tuple[ Int, Int, Int, Optional[Int] ];
|
||||
|
||||
Of course, you could always use objects to represent these sorts of
|
||||
things too.
|
||||
|
||||
=head2 L<MooseX::ClassAttribute>
|
||||
|
||||
This extension provides class attributes for Moose classes. The
|
||||
declared class attributes are introspectable just like regular Moose
|
||||
attributes.
|
||||
|
||||
package User;
|
||||
|
||||
use Moose;
|
||||
use MooseX::ClassAttribute;
|
||||
|
||||
has 'name' => ( ... );
|
||||
|
||||
class_has 'Cache' => ( ... );
|
||||
|
||||
Note however that this class attribute does I<not> inherit like a
|
||||
L<Class::Data::Inheritable> or similar attribute - calling
|
||||
|
||||
$subclass->Cache($cache);
|
||||
|
||||
will set it for the superclass as well. Additionally, class data is usually
|
||||
The Wrong Thing To Do in a strongly OO program since it makes testing a
|
||||
lot harder - consider carefully whether you'd be better off with an object
|
||||
that's passed around instead.
|
||||
|
||||
=head2 L<MooseX::Daemonize>
|
||||
|
||||
This is a role that provides a number of methods useful for creating a
|
||||
daemon, including methods for starting and stopping, managing a PID
|
||||
file, and signal handling.
|
||||
|
||||
=head2 L<MooseX::Role::Parameterized>
|
||||
|
||||
If you find yourself wanting a role that customizes itself for each
|
||||
consumer, this is the tool for you. With this module, you can create a
|
||||
role that accepts parameters and generates attributes, methods, etc. on
|
||||
a customized basis for each consumer.
|
||||
|
||||
=head2 L<MooseX::POE>
|
||||
|
||||
This is a small wrapper that ties together a Moose class with
|
||||
C<POE::Session>, and gives you an C<event> sugar function to declare
|
||||
event handlers.
|
||||
|
||||
=head2 L<MooseX::FollowPBP>
|
||||
|
||||
Automatically names all accessors I<Perl Best Practices>-style,
|
||||
"get_size" and "set_size".
|
||||
|
||||
=head2 L<MooseX::SemiAffordanceAccessor>
|
||||
|
||||
Automatically names all accessors with an explicit set and implicit
|
||||
get, "size" and "set_size".
|
||||
|
||||
=head2 L<MooseX::NonMoose>
|
||||
|
||||
MooseX::NonMoose allows for easily subclassing non-Moose classes with Moose,
|
||||
taking care of the annoying details connected with doing this, such as
|
||||
setting up proper inheritance from Moose::Object and installing
|
||||
(and inlining, at make_immutable time) a constructor that makes sure things
|
||||
like BUILD methods are called.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
Stevan Little <stevan@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=item *
|
||||
|
||||
Jesse Luehrs <doy@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Shawn M Moore <sartak@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
|
||||
|
||||
=item *
|
||||
|
||||
Karen Etheridge <ether@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Florian Ragwitz <rafl@debian.org>
|
||||
|
||||
=item *
|
||||
|
||||
Hans Dieter Pearcey <hdp@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Chris Prather <chris@prather.org>
|
||||
|
||||
=item *
|
||||
|
||||
Matt S Trout <mstrout@cpan.org>
|
||||
|
||||
=back
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2006 by Infinity Interactive, Inc.
|
||||
|
||||
This is free software; you can redistribute it and/or modify it under
|
||||
the same terms as the Perl 5 programming language system itself.
|
||||
|
||||
=cut
|
||||
526
CPAN/Moose/Manual/Resources.pod
Normal file
526
CPAN/Moose/Manual/Resources.pod
Normal file
@@ -0,0 +1,526 @@
|
||||
# PODNAME: Moose::Manual::Resources
|
||||
# ABSTRACT: Links to various tutorials, videos, blogs, presentations, interviews, etc...
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Moose::Manual::Resources - Links to various tutorials, videos, blogs, presentations, interviews, etc...
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 2.2207
|
||||
|
||||
=head1 Resources
|
||||
|
||||
This section is an attempt to collect and list some of the many Moose resources that can be found online. Additional information can be found at http://moose.perl.org/
|
||||
|
||||
=head2 Videos
|
||||
|
||||
=over 4
|
||||
|
||||
=item
|
||||
|
||||
A new object system for the Perl 5 core, Stevan Little
|
||||
L<https://www.youtube.com/watch?v=Gf0O6Ct7V1s>
|
||||
|
||||
=item
|
||||
|
||||
Stevan Little interviewed by Gabor Szabo for PerlMaven.com
|
||||
L<https://www.youtube.com/watch?v=shu-bVimOpM>
|
||||
|
||||
=item
|
||||
|
||||
Perl 6 OO vs. Moose, Herbert Breunung
|
||||
L<https://www.youtube.com/watch?v=Boh3109HVLo>
|
||||
|
||||
=item
|
||||
|
||||
Introduction To Moose, Mike Whitaker
|
||||
L<https://www.youtube.com/watch?v=YVtqa6zWXqY>
|
||||
|
||||
=item
|
||||
|
||||
"Dr. Strange... Moose or: How I Learned to Stop Worrying and Love Perl"
|
||||
L<https://www.youtube.com/watch?v=PNFiIU8S-7g>
|
||||
|
||||
=item
|
||||
|
||||
Evolving Software with Moose, Dave Cross
|
||||
L<https://www.youtube.com/watch?v=BIMREkoPYKA>
|
||||
|
||||
=item
|
||||
|
||||
Testing with Test::Class::Moose, Curtis Poe
|
||||
L<https://www.youtube.com/watch?v=kUHI1iRrfF4>
|
||||
|
||||
=item
|
||||
|
||||
"Moose is Perl" tutorial, OSCON 2014, Ricardo Signes
|
||||
L<https://www.youtube.com/watch?v=LKXvG6VKew4>
|
||||
|
||||
=back
|
||||
|
||||
=head2 Slide Shows
|
||||
|
||||
=over 4
|
||||
|
||||
=item
|
||||
|
||||
Use Moose to create abstractions in the domain, Shawn M. Moore (sartak)
|
||||
L<https://speakerdeck.com/sartak/lifting-moose>
|
||||
|
||||
=back
|
||||
|
||||
=head2 Articles
|
||||
|
||||
=over 4
|
||||
|
||||
=item
|
||||
|
||||
Perl.org Moose Whitepaper
|
||||
L<https://www.perl.org/about/whitepapers/perl-object-oriented.html>
|
||||
|
||||
=item
|
||||
|
||||
PerlMaven.com
|
||||
L<http://perlmaven.com/moose>
|
||||
|
||||
=item
|
||||
|
||||
Getting Started with Moose, brian d foy
|
||||
http://www.theperlreview.com/articles/moose.html
|
||||
|
||||
=item
|
||||
|
||||
Wikipedia.org
|
||||
L<http://en.wikipedia.org/wiki/Moose_(Perl)>
|
||||
|
||||
=item
|
||||
|
||||
Moose: A postmodern object system for Perl 5
|
||||
L<http://perltraining.com.au/tips/2010-01-27.html>
|
||||
|
||||
=item
|
||||
|
||||
Roles and Delegates and Refactoring
|
||||
L<http://blog.woobling.org/2009/10/roles-and-delegates-and-refactoring.html>
|
||||
|
||||
=back
|
||||
|
||||
=head1 Older Resources
|
||||
|
||||
=head2 Articles
|
||||
|
||||
=head3 2011
|
||||
|
||||
=over 4
|
||||
|
||||
=item
|
||||
|
||||
Dave Rolsky reviews Perl Best Practices, Chapter 15, Objects 7 years later
|
||||
L<http://blog.urth.org/2011/03/reviewing-perl-best-practices-chapter-15-objects.html>
|
||||
|
||||
=item
|
||||
|
||||
Mark A. Stratman discusses subclassing non-Moose classes
|
||||
L<http://blogs.perl.org/users/mark_a_stratman/2011/03/subclassing-tricky-non-moose-classes-constructor-problems.html>
|
||||
|
||||
=item
|
||||
|
||||
Mark A. Stratman shows how to use delegation to work with non-Moose classes
|
||||
L<http://blogs.perl.org/users/mark_a_stratman/2011/03/subclassing-tricky-non-moose-classes-dont-do-it.html>
|
||||
|
||||
=item
|
||||
|
||||
The WebGUI folks talk about version 8.0 (which uses Moose)
|
||||
L<http://blogs.perl.org/users/preaction/2011/01/whats-new-in-webgui-80-1---psgiplack.html>
|
||||
|
||||
=item
|
||||
|
||||
chromatic discusses Parameterized roles with Moose
|
||||
L<http://www.modernperlbooks.com/mt/2011/01/the-parametric-role-of-my-mvc-plugin-system.html>
|
||||
|
||||
=back
|
||||
|
||||
=head3 2010
|
||||
|
||||
=over 4
|
||||
|
||||
=item
|
||||
|
||||
Chris Prather discusses Moose and the Modern Perl movement
|
||||
L<http://chris.prather.org/been-there-done-that.md.html>
|
||||
|
||||
=item
|
||||
|
||||
Devin Austin talks about MooseX::App::Cmd
|
||||
L<http://www.catalyzed.org/2010/04/moosexappcmd-and-your-command-line-apps.html>
|
||||
|
||||
=item
|
||||
|
||||
JT Smith declares The Second Age of Perl
|
||||
L<http://blogs.perl.org/users/jt_smith/2010/04/the-second-age-of-perl.html>
|
||||
|
||||
=item
|
||||
|
||||
JT Smith talks about Lacuna Expanse (which uses Moose)
|
||||
L<http://blogs.perl.org/users/jt_smith/2010/10/why-the-lacuna-expanse-is-good-for-perl.html>
|
||||
|
||||
=item
|
||||
|
||||
Moose 1.00 is Released
|
||||
L<http://stevan-little.blogspot.com/2010/03/moose-100-is-released.html>
|
||||
|
||||
=item
|
||||
|
||||
Moritz Lenz asks What is "Modern Perl"?
|
||||
L<http://perlgeek.de/blog-en/perl-tips/what-is-modern-perl.html>
|
||||
|
||||
=item
|
||||
|
||||
Yuval Kogman declares "Moose has won".
|
||||
L<http://blog.woobling.org/2010/09/moose-has-won.html>
|
||||
|
||||
=item
|
||||
|
||||
chromatic discusses how Moose helps you write more correct code
|
||||
L<http://www.modernperlbooks.com/mt/2010/01/subtle-encouragement-toward-correctness.html>
|
||||
|
||||
=item
|
||||
|
||||
chromatic discusses the Moose deprecation policy
|
||||
L<http://www.modernperlbooks.com/mt/2010/09/the-right-approach-to-deprecation.html>
|
||||
|
||||
=item
|
||||
|
||||
chromatic talks about Class::MOP in relation to his Modern Perl book
|
||||
L<http://www.modernperlbooks.com/mt/2010/03/ill-get-the-mop.html>
|
||||
|
||||
=item
|
||||
|
||||
chromatic talks about Encapsulation and Moose
|
||||
L<http://www.modernperlbooks.com/mt/2010/09/what-you-can-and-cannot-teach-about-encapsulation.html>
|
||||
|
||||
=back
|
||||
|
||||
=head3 2009
|
||||
|
||||
=over 4
|
||||
|
||||
=item
|
||||
|
||||
Bruno Vecchi praises Moose for making his protein analysis code easier
|
||||
L<http://zerothorder.blogspot.com/2009/04/chopping-proteins-with-moose.html>
|
||||
|
||||
=item
|
||||
|
||||
Chris Prather compares MooseX::Declare to Simula 67
|
||||
L<http://chris.prather.org/a-little-bit-of-history.md.html>
|
||||
|
||||
=item
|
||||
|
||||
Chris Prather rationalizes Moose's "post modern" label
|
||||
L<http://chris.prather.org/why-moose-is-post-modern.html>
|
||||
|
||||
=item
|
||||
|
||||
Dave Rolsky's post-mortem on his Moose documentation grant
|
||||
L<http://blog.urth.org/2009/04/moose-docs-grant-wrap-up.html>
|
||||
|
||||
=item
|
||||
|
||||
David McLaughlin experiments with extending Moose for MooseX::ChainedAccessors
|
||||
L<http://www.dmclaughlin.com/2009/05/15/chained-accessors-in-moose/>
|
||||
|
||||
=item
|
||||
|
||||
Sam Crawley summarizes his experience with roles
|
||||
L<http://samcrawley.wordpress.com/2009/05/03/getting-the-hang-of-moose-roles/>
|
||||
|
||||
=item
|
||||
|
||||
Shawn M Moore discusses Perl::Critic for Moose and linting with the MOP
|
||||
L<http://blog.sartak.org/2009/05/perl-critic-dynamic-moose.html>
|
||||
|
||||
=item
|
||||
|
||||
Shlomi Fish discovers a better way to Moose
|
||||
L<http://community.livejournal.com/shlomif_tech/38407.html>
|
||||
|
||||
=item
|
||||
|
||||
Stevan Little explains why you should make your Moose classes immutable
|
||||
L<http://stevan-little.blogspot.com/2009/06/why-makeimmutable-is-recommended-for_13.html>
|
||||
|
||||
=item
|
||||
|
||||
Tomas Doran interview about the new Moose-based Catalyst
|
||||
L<http://www.catalyzed.org/2009/04/catalyst-58-released.html>
|
||||
|
||||
=item
|
||||
|
||||
chromatic contrasts roles and duck-typing
|
||||
L<http://www.modernperlbooks.com/mt/2009/05/perl-roles-versus-duck-typing.html>
|
||||
|
||||
=item
|
||||
|
||||
chromatic contrasts roles and inheritance
|
||||
L<http://www.modernperlbooks.com/mt/2009/05/perl-roles-versus-inheritance.html>
|
||||
|
||||
=item
|
||||
|
||||
chromatic on The Why of Perl Roles
|
||||
L<http://www.modernperlbooks.com/mt/2009/04/the-why-of-perl-roles.html>
|
||||
|
||||
=back
|
||||
|
||||
=head3 2008
|
||||
|
||||
=over 4
|
||||
|
||||
=item
|
||||
|
||||
Barry Walsh does an excellent comparison of Moose and Ruby (specifically the Doodle module)
|
||||
L<http://draegtun.wordpress.com/2008/03/12/doodling-with-moose-part-1/>
|
||||
|
||||
=item
|
||||
|
||||
Tim Bunce's excellent Perl Myths talk gives a shout out to Moose
|
||||
L<http://www.slideshare.net/Tim.Bunce/perl-myths-200802-with-notes/>
|
||||
|
||||
=item
|
||||
|
||||
chromatic suggests Moose and Mouse in his Beginners Introduction to Object-Oriented Programming with Perl article
|
||||
L<http://broadcast.oreilly.com/2008/11/beginners-introduction-to-obje.html>
|
||||
|
||||
=back
|
||||
|
||||
=head3 2007
|
||||
|
||||
=over 4
|
||||
|
||||
=item
|
||||
|
||||
Larry mentioned Moose in 2007's State of the Onion speech
|
||||
L<http://www.perl.com/pub/a/2007/12/06/soto-11.html?page=3>
|
||||
|
||||
=item
|
||||
|
||||
Max Kanat-Alexander (of Bugzilla fame) has some nice things to say about Moose
|
||||
L<http://avatraxiom.livejournal.com/70947.html>
|
||||
|
||||
=back
|
||||
|
||||
=head3 2006
|
||||
|
||||
=over 4
|
||||
|
||||
=item
|
||||
|
||||
Class::MOP Review (OnLAMP)
|
||||
L<http://www.oreillynet.com/onlamp/blog/2006/06/cpan_module_review_classmop.html>
|
||||
|
||||
=back
|
||||
|
||||
=head2 Presentations
|
||||
|
||||
=head3 Perl Mongers Groups
|
||||
|
||||
=over 4
|
||||
|
||||
=item
|
||||
|
||||
Doug Treder's Moose talk at Seattle Perl Users Group
|
||||
L<http://www.slideshare.net/dtreder/moose-527243>
|
||||
|
||||
=item
|
||||
|
||||
Hans Dieter Pearcey's Meta-Moose at PDX.pm
|
||||
L<http://www.weftsoar.net/~hdp/talk/meta-moose/slides/start.html>
|
||||
|
||||
=item
|
||||
|
||||
Piers Cawley's MooseX::Declare talk at London.pm (video)
|
||||
L<http://www.bofh.org.uk/2009/05/13/london-pm-presentation>
|
||||
|
||||
=item
|
||||
|
||||
Robert Boone's Moose talk at Houston.pm
|
||||
L<http://houston.pm.org/talks/2007talks/0704Talk/slides/start.html>
|
||||
|
||||
=item
|
||||
|
||||
hakobe's Moose presentation at Kansai.pm
|
||||
L<http://www.slideshare.net/hakobe/moose>
|
||||
|
||||
=back
|
||||
|
||||
=head3 2011
|
||||
|
||||
=over 4
|
||||
|
||||
=item
|
||||
|
||||
SawyerX's FOSDEM 2011 Moose talk
|
||||
L<http://www.slideshare.net/xSawyer/moose-talk-at-fosdem-2011-perl-devroom>
|
||||
|
||||
=back
|
||||
|
||||
=head3 2010
|
||||
|
||||
=over 4
|
||||
|
||||
=item
|
||||
|
||||
Drew Stephens gives a lighting talk on Moose at SHDH 36
|
||||
L<http://www.slideshare.net/dinomite/learning-moose-lightning>
|
||||
|
||||
=item
|
||||
|
||||
Jesse Luehrs's "Extending Moose" talk at YAPC::NA 2010
|
||||
L<http://tozt.net/talks/extending_moose_yapc_na_2010/>
|
||||
|
||||
=item
|
||||
|
||||
Shawn Moore's "Non-hierarchical osdc.tw
|
||||
L<http://sartak.org/talks/osdc.tw-2010/nonhierarchical-oop/nonhierarchical-oop.pdf>
|
||||
|
||||
=item
|
||||
|
||||
Ynon Perek's Perl Object Oriented Programming slides
|
||||
L<http://prezi.com/fgdoyw0smyqo/perl-object-oriented-programming/>
|
||||
|
||||
=back
|
||||
|
||||
=head3 2009
|
||||
|
||||
=over 4
|
||||
|
||||
=item
|
||||
|
||||
Dave Rolsky's Introduction to Moose master class at YAPC::NA 2009 (delivered by Shawn Moore and Jonathan Rockway)
|
||||
L<http://yapc10.org/yn2009/talk/2047>
|
||||
|
||||
=item
|
||||
|
||||
Devin Austin's Intro to Moose at YAPC::NA 2009
|
||||
L<http://yapc10.org/yn2009/talk/1967>
|
||||
|
||||
=item
|
||||
|
||||
Hans Dieter Pearcey's Code Reuse with Moose at YAPC::NA 2009
|
||||
L<http://yapc10.org/yn2009/talk/1984>
|
||||
|
||||
=item
|
||||
|
||||
Mike Whitaker's Intro to Moose at Italian Perl Workshop
|
||||
L<http://www.slideshare.net/Penfold/introduction-to-moose-2437037>
|
||||
|
||||
=item
|
||||
|
||||
Mike Whitaker's Introduction to Moose at the Italian Perl Workshop
|
||||
L<http://conferences.yapceurope.org/ipw2009/talk/2371>
|
||||
|
||||
=item
|
||||
|
||||
Shawn M Moore's Intro to Moose at Frozen Perl
|
||||
L<http://sartak.org/talks/frozen-perl-2009/moose/>
|
||||
|
||||
=item
|
||||
|
||||
Shawn Moore's Extending Moose for Applications at YAPC::NA 2009
|
||||
L<http://sartak.org/talks/yapc-na-2009/extending-moose/extending-moose.pdf>
|
||||
|
||||
=item
|
||||
|
||||
Shawn Moore's Moose master class at YAPC::Asia 2009
|
||||
L<http://conferences.yapcasia.org/ya2009/talk/2192>
|
||||
|
||||
=item
|
||||
|
||||
Yuval Kogman's Why Moose at the Nordic Perl Workshop
|
||||
L<http://www.perlworkshop.no/npw2009/talk/1901>
|
||||
|
||||
=back
|
||||
|
||||
=head3 2008
|
||||
|
||||
=over 4
|
||||
|
||||
=item
|
||||
|
||||
Mike Whitaker's Intro to Moose at the London Perl Workshop
|
||||
L<http://yapc.tv/2008/lpw/mike-whitaker-intro-moose/>
|
||||
|
||||
=back
|
||||
|
||||
=head3 2006
|
||||
|
||||
=over 4
|
||||
|
||||
=item
|
||||
|
||||
Sam Vilain gives the very first Moose talk at YAPC::EU
|
||||
L<http://www.yapceurope.org/2006/talk/item/63.html>
|
||||
|
||||
=back
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
Stevan Little <stevan@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=item *
|
||||
|
||||
Jesse Luehrs <doy@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Shawn M Moore <sartak@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
|
||||
|
||||
=item *
|
||||
|
||||
Karen Etheridge <ether@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Florian Ragwitz <rafl@debian.org>
|
||||
|
||||
=item *
|
||||
|
||||
Hans Dieter Pearcey <hdp@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Chris Prather <chris@prather.org>
|
||||
|
||||
=item *
|
||||
|
||||
Matt S Trout <mstrout@cpan.org>
|
||||
|
||||
=back
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2006 by Infinity Interactive, Inc.
|
||||
|
||||
This is free software; you can redistribute it and/or modify it under
|
||||
the same terms as the Perl 5 programming language system itself.
|
||||
|
||||
=cut
|
||||
557
CPAN/Moose/Manual/Roles.pod
Normal file
557
CPAN/Moose/Manual/Roles.pod
Normal file
@@ -0,0 +1,557 @@
|
||||
# PODNAME: Moose::Manual::Roles
|
||||
# ABSTRACT: Roles, an alternative to deep hierarchies and base classes
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Moose::Manual::Roles - Roles, an alternative to deep hierarchies and base classes
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 2.2207
|
||||
|
||||
=head1 WHAT IS A ROLE?
|
||||
|
||||
A role encapsulates some piece of behavior or state that can be shared between
|
||||
classes. It is something that classes I<do>. It is important to understand that
|
||||
I<roles are not classes>. You cannot inherit from a role, and a role cannot be
|
||||
instantiated. We sometimes say that roles are I<consumed>, either by classes
|
||||
or other roles.
|
||||
|
||||
Instead, a role is I<composed> into a class. In practical terms, this
|
||||
means that all of the methods, method modifiers, and attributes defined in a role are
|
||||
added directly to (we sometimes say "flattened into") the class that
|
||||
consumes the role. These attributes and methods then appear as if they
|
||||
were defined in the class itself. A subclass of the consuming class
|
||||
will inherit all of these methods and attributes.
|
||||
|
||||
Moose roles are similar to mixins or interfaces in other languages and are
|
||||
based on the L<original concept of Traits|http://scg.unibe.ch/research/traits/>
|
||||
for the Smalltalk-80 dialect Squeak.
|
||||
|
||||
Besides defining their own methods and attributes, roles can also
|
||||
require that the consuming class define certain methods of its
|
||||
own. You could have a role that consisted only of a list of required
|
||||
methods, in which case the role would be very much like a Java
|
||||
interface.
|
||||
|
||||
Note that attribute accessors also count as methods for the
|
||||
purposes of satisfying the requirements of a role.
|
||||
|
||||
=head1 A SIMPLE ROLE
|
||||
|
||||
Creating a role looks a lot like creating a Moose class:
|
||||
|
||||
package Breakable;
|
||||
|
||||
use Moose::Role;
|
||||
|
||||
has 'is_broken' => (
|
||||
is => 'rw',
|
||||
isa => 'Bool',
|
||||
);
|
||||
|
||||
sub break {
|
||||
my $self = shift;
|
||||
|
||||
print "I broke\n";
|
||||
|
||||
$self->is_broken(1);
|
||||
}
|
||||
|
||||
Except for our use of L<Moose::Role>, this looks just like a class
|
||||
definition with Moose. However, this is not a class, and it cannot be
|
||||
instantiated.
|
||||
|
||||
Instead, its attributes and methods will be composed into classes
|
||||
which use the role:
|
||||
|
||||
package Car;
|
||||
|
||||
use Moose;
|
||||
|
||||
with 'Breakable';
|
||||
|
||||
has 'engine' => (
|
||||
is => 'ro',
|
||||
isa => 'Engine',
|
||||
);
|
||||
|
||||
The C<with> function composes roles into a class. Once that is done,
|
||||
the C<Car> class has an C<is_broken> attribute and a C<break>
|
||||
method. The C<Car> class also C<does('Breakable')>:
|
||||
|
||||
my $car = Car->new( engine => Engine->new );
|
||||
|
||||
print $car->is_broken ? 'Busted' : 'Still working';
|
||||
$car->break;
|
||||
print $car->is_broken ? 'Busted' : 'Still working';
|
||||
|
||||
$car->does('Breakable'); # true
|
||||
|
||||
This prints:
|
||||
|
||||
Still working
|
||||
I broke
|
||||
Busted
|
||||
|
||||
We could use this same role in a C<Bone> class:
|
||||
|
||||
package Bone;
|
||||
|
||||
use Moose;
|
||||
|
||||
with 'Breakable';
|
||||
|
||||
has 'marrow' => (
|
||||
is => 'ro',
|
||||
isa => 'Marrow',
|
||||
);
|
||||
|
||||
See also L<Moose::Cookbook::Roles::Comparable_CodeReuse> for an example.
|
||||
|
||||
It's possible to compose existing roles into new roles. For example, we can
|
||||
have a C<HandleWithCare> class which applies both the C<Breakable> and
|
||||
C<Package> roles to any class which consumes it:
|
||||
|
||||
package HandleWithCare;
|
||||
|
||||
use Moose::Role;
|
||||
|
||||
with 'Breakable', 'Package';
|
||||
|
||||
=head1 REQUIRED METHODS
|
||||
|
||||
As mentioned previously, a role can require that consuming classes
|
||||
provide one or more methods. Using our C<Breakable> example, let's
|
||||
make it require that consuming classes implement their own C<break>
|
||||
methods:
|
||||
|
||||
package Breakable;
|
||||
|
||||
use Moose::Role;
|
||||
|
||||
requires 'break';
|
||||
|
||||
has 'is_broken' => (
|
||||
is => 'rw',
|
||||
isa => 'Bool',
|
||||
);
|
||||
|
||||
after 'break' => sub {
|
||||
my $self = shift;
|
||||
|
||||
$self->is_broken(1);
|
||||
};
|
||||
|
||||
If we try to consume this role in a class that does not have a
|
||||
C<break> method, we will get an exception.
|
||||
|
||||
You can see that we added a method modifier on C<break>. We want
|
||||
classes that consume this role to implement their own logic for
|
||||
breaking, but we make sure that the C<is_broken> attribute is always
|
||||
set to true when C<break> is called.
|
||||
|
||||
package Car
|
||||
|
||||
use Moose;
|
||||
|
||||
with 'Breakable';
|
||||
|
||||
has 'engine' => (
|
||||
is => 'ro',
|
||||
isa => 'Engine',
|
||||
);
|
||||
|
||||
sub break {
|
||||
my $self = shift;
|
||||
|
||||
if ( $self->is_moving ) {
|
||||
$self->stop;
|
||||
}
|
||||
}
|
||||
|
||||
=head2 Roles Versus Abstract Base Classes
|
||||
|
||||
If you are familiar with the concept of abstract base classes in other
|
||||
languages, you may be tempted to use roles in the same way.
|
||||
|
||||
You I<can> define an "interface-only" role, one that contains I<just>
|
||||
a list of required methods.
|
||||
|
||||
However, any class which consumes this role must implement all of the
|
||||
required methods, either directly or through inheritance from a
|
||||
parent. You cannot delay the method requirement check so that they can
|
||||
be implemented by future subclasses.
|
||||
|
||||
Because the role defines the required methods directly, adding a base
|
||||
class to the mix would not achieve anything. We recommend that you
|
||||
simply consume the interface role in each class which implements that
|
||||
interface.
|
||||
|
||||
=head1 CONSUMING ROLES
|
||||
|
||||
Roles are consumed using the C<with> function.
|
||||
|
||||
Most of the time, you should only use one C<with>, even if you are consuming
|
||||
multiple roles. If you consume roles using multiple C<with> statements Moose
|
||||
cannot detect method conflicts between those roles.
|
||||
|
||||
Roles can be consumed by classes or by other roles. When a class consumes a
|
||||
role which in turn consumes other roles, the class gets all of the roles
|
||||
applied at once.
|
||||
|
||||
=head2 Required Methods Provided by Attributes
|
||||
|
||||
As mentioned before, a role's required method may also be satisfied by an
|
||||
attribute accessor. However, the call to C<has> which defines an attribute
|
||||
happens at runtime. This means that you must define the attribute I<before>
|
||||
consuming the role, or else the role will not see the generated accessor.
|
||||
These attributes are L<Moose Attributes|Moose::Manual::Attributes>.
|
||||
|
||||
package Breakable;
|
||||
|
||||
use Moose::Role;
|
||||
|
||||
requires 'stress';
|
||||
|
||||
########
|
||||
|
||||
package Car;
|
||||
|
||||
use Moose;
|
||||
|
||||
has 'stress' => (
|
||||
is => 'ro',
|
||||
isa => 'Int',
|
||||
);
|
||||
|
||||
with 'Breakable';
|
||||
|
||||
In general, we recommend that you always consume roles I<after> declaring all
|
||||
your attributes.
|
||||
|
||||
It may also be the case that a class wants to consume two roles where one role
|
||||
has an attribute providing a required method for another. For example:
|
||||
|
||||
package Breakable;
|
||||
|
||||
use Moose::Role;
|
||||
|
||||
requires 'stress';
|
||||
|
||||
########
|
||||
|
||||
package Stressable;
|
||||
|
||||
use Moose::Role;
|
||||
|
||||
has 'stress' => (
|
||||
is => 'ro',
|
||||
isa => 'Int',
|
||||
);
|
||||
|
||||
########
|
||||
|
||||
package Car;
|
||||
|
||||
use Moose;
|
||||
|
||||
# XXX - this will not work
|
||||
with 'Breakable', 'Stressable';
|
||||
|
||||
However, this won't work. The problem is that the accessor methods created for
|
||||
the C<stress> attribute won't be present in the class when the required method
|
||||
checks are done.
|
||||
|
||||
There are two possible workarounds. The recommended one is to use "stub"
|
||||
subroutine(s) in the role providing the accessor(s):
|
||||
|
||||
package Stressable;
|
||||
|
||||
use Moose::Role;
|
||||
|
||||
sub stress;
|
||||
has 'stress' => (
|
||||
is => 'ro',
|
||||
isa => 'Int',
|
||||
);
|
||||
|
||||
The C<sub stress;> line is called a "forward" declaration in the Perl
|
||||
documentation. It creates what is called a "stub" subroutine, a declaration
|
||||
without a body. This is good enough to satisfy the required method checks done
|
||||
by Moose. The stub will not interfere with the creation of a real subroutine
|
||||
later.
|
||||
|
||||
The other alternative is to use two separate calls to C<with> in the consuming
|
||||
class:
|
||||
|
||||
package Car;
|
||||
|
||||
use Moose;
|
||||
|
||||
# Not recommended
|
||||
with 'Stressable';
|
||||
with 'Breakable';
|
||||
|
||||
Each C<with> is run as it is seen. The first call will consume just the
|
||||
C<Stressable> role, which will add the C<stress> attribute to the C<Car>
|
||||
package, which in turn will create an accessor method named C<stress>. Then
|
||||
when the C<Breakable> role is consumed, the method it requires already exists.
|
||||
|
||||
However, as mentioned earlier, multiple C<with> declarations are not
|
||||
recommended, because method conflicts between the roles cannot be seen. In the
|
||||
example above, if both C<Stressable> and C<Breakable> contained methods of the
|
||||
same name, what would happen is that the version in C<Stressable> would
|
||||
I<silently> override the one in C<Breakable>.
|
||||
|
||||
=head1 USING METHOD MODIFIERS
|
||||
|
||||
Method modifiers and roles are a very powerful combination. Often, a
|
||||
role will combine method modifiers and required methods. We already
|
||||
saw one example with our C<Breakable> example.
|
||||
|
||||
Method modifiers increase the complexity of roles, because they make
|
||||
the role application order relevant. If a class uses multiple roles,
|
||||
each of which modify the same method, those modifiers will be applied
|
||||
in the same order as the roles are used:
|
||||
|
||||
package MovieCar;
|
||||
|
||||
use Moose;
|
||||
|
||||
extends 'Car';
|
||||
|
||||
with 'Breakable', 'ExplodesOnBreakage';
|
||||
|
||||
Assuming that the new C<ExplodesOnBreakage> role I<also> has an
|
||||
C<after> modifier on C<break>, the C<after> modifiers will run one
|
||||
after the other. The modifier from C<Breakable> will run first, then
|
||||
the one from C<ExplodesOnBreakage>.
|
||||
|
||||
=head1 METHOD CONFLICTS
|
||||
|
||||
If a class composes multiple roles, and those roles have methods of
|
||||
the same name, we will have a conflict. In that case, the composing
|
||||
class is required to provide its I<own> method of the same name.
|
||||
|
||||
package Breakdancer;
|
||||
|
||||
use Moose::Role;
|
||||
|
||||
sub break {
|
||||
|
||||
}
|
||||
|
||||
If we compose both C<Breakable> and C<Breakdancer> in a class, we must
|
||||
provide our own C<break> method:
|
||||
|
||||
package FragileDancer;
|
||||
|
||||
use Moose;
|
||||
|
||||
with 'Breakable', 'Breakdancer';
|
||||
|
||||
sub break { ... }
|
||||
|
||||
A role can be a collection of other roles:
|
||||
|
||||
package Break::Bundle;
|
||||
|
||||
use Moose::Role;
|
||||
|
||||
with ('Breakable', 'Breakdancer');
|
||||
|
||||
When a role consumes another a role, the I<consuming> role's methods silently
|
||||
win in any conflict, and the consumed role's methods are simply ignored.
|
||||
|
||||
=head1 METHOD EXCLUSION AND ALIASING
|
||||
|
||||
If we want our C<FragileDancer> class to be able to call the methods
|
||||
from both its roles, we can alias the methods:
|
||||
|
||||
package FragileDancer;
|
||||
|
||||
use Moose;
|
||||
|
||||
with 'Breakable' => { -alias => { break => 'break_bone' } },
|
||||
'Breakdancer' => { -alias => { break => 'break_dance' } };
|
||||
|
||||
However, aliasing a method simply makes a I<copy> of the method with
|
||||
the new name. We also need to exclude the original name:
|
||||
|
||||
with 'Breakable' => {
|
||||
-alias => { break => 'break_bone' },
|
||||
-excludes => 'break',
|
||||
},
|
||||
'Breakdancer' => {
|
||||
-alias => { break => 'break_dance' },
|
||||
-excludes => 'break',
|
||||
};
|
||||
|
||||
The excludes parameter prevents the C<break> method from being composed
|
||||
into the C<FragileDancer> class, so we don't have a conflict. This
|
||||
means that C<FragileDancer> does not need to implement its own
|
||||
C<break> method.
|
||||
|
||||
This is useful, but it's worth noting that this breaks the contract
|
||||
implicit in consuming a role. Our C<FragileDancer> class does both the
|
||||
C<Breakable> and C<BreakDancer>, but does not provide a C<break>
|
||||
method. If some API expects an object that does one of those roles, it
|
||||
probably expects it to implement that method.
|
||||
|
||||
In some use cases we might alias and exclude methods from roles, but
|
||||
then provide a method of the same name in the class itself.
|
||||
|
||||
Also see L<Moose::Cookbook::Roles::Restartable_AdvancedComposition> for an example.
|
||||
|
||||
=head1 OVERLOADING
|
||||
|
||||
When a Moose role uses overloading, that overloading is composed into any
|
||||
classes that consume the role. This includes the setting of the C<fallback>
|
||||
value for that role's overloading. Just as with methods and attributes, when a
|
||||
role consumes another role, that other role's overloading settings are applied
|
||||
to the role.
|
||||
|
||||
Just as with methods, there can be conflicts with overloading implementations
|
||||
between multiple roles when they are all consumed by a class. If two roles
|
||||
both provide different overloading implementations for a given operator, that
|
||||
is a conflict. If two roles both implement overloading and have different
|
||||
C<fallback> values, that is also considered a conflict. These conflicts are
|
||||
detected when multiple roles are being composed into a class together.
|
||||
|
||||
When a role consumes another role, the consuming role's overloading fallback
|
||||
and operator implementations silently "win" the conflict.
|
||||
|
||||
=head1 ROLE EXCLUSION
|
||||
|
||||
A role can say that it cannot be combined with some other role. This
|
||||
should be used with great caution, since it limits the re-usability of
|
||||
the role.
|
||||
|
||||
package Breakable;
|
||||
|
||||
use Moose::Role;
|
||||
|
||||
excludes 'BreakDancer';
|
||||
|
||||
=head1 ADDING A ROLE TO AN OBJECT INSTANCE
|
||||
|
||||
You may want to add a role to an object instance, rather than to a class. For
|
||||
example, you may want to add debug tracing to one instance of an object while
|
||||
debugging a particular bug. Another use case might be to dynamically change
|
||||
objects based on a user's configuration, as a plugin system.
|
||||
|
||||
The best way to do this is to use the C<apply_all_roles()> function from
|
||||
L<Moose::Util>:
|
||||
|
||||
use Moose::Util qw( apply_all_roles );
|
||||
|
||||
my $car = Car->new;
|
||||
apply_all_roles( $car, 'Breakable' );
|
||||
|
||||
This function can apply more than one role at a time, and will do so using the
|
||||
normal Moose role combination system. We recommend using this function to
|
||||
apply roles to an object. This is what Moose uses internally when you call
|
||||
C<with>.
|
||||
|
||||
=head2 Handling required attributes for roles.
|
||||
|
||||
Application of some roles will require additional parameters being specified to
|
||||
satisfy them, for example:
|
||||
|
||||
{
|
||||
package Car;
|
||||
use Moose;
|
||||
}
|
||||
{
|
||||
package Breakable;
|
||||
use Moose::Role;
|
||||
|
||||
has 'breakable_parts' => ( is => 'ro', required => 1 );
|
||||
}
|
||||
|
||||
my $car = Car->new;
|
||||
|
||||
# next line dies with: Attribute (breakable_parts) is required
|
||||
apply_all_roles( $car, 'Breakable' );
|
||||
|
||||
This will require passing the additional parameters at application time as
|
||||
follows:
|
||||
|
||||
apply_all_roles( $car, 'Breakable' => {
|
||||
rebless_params => {
|
||||
# Parameters to 'Breakable'
|
||||
breakable_parts => [qw( tires wheels windscreen )],
|
||||
}
|
||||
});
|
||||
|
||||
Obviously, this interface is better simplified as a method on C<Car>:
|
||||
|
||||
sub make_breakable {
|
||||
my ( $self, %params ) = @_;
|
||||
apply_all_roles($self, 'Breakable', { rebless_params => \%params });
|
||||
}
|
||||
|
||||
my $car = Car->new();
|
||||
$car->make_breakable( breakable_parts => [qw( tires wheels windscreen )] );
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
Stevan Little <stevan@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=item *
|
||||
|
||||
Jesse Luehrs <doy@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Shawn M Moore <sartak@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
|
||||
|
||||
=item *
|
||||
|
||||
Karen Etheridge <ether@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Florian Ragwitz <rafl@debian.org>
|
||||
|
||||
=item *
|
||||
|
||||
Hans Dieter Pearcey <hdp@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Chris Prather <chris@prather.org>
|
||||
|
||||
=item *
|
||||
|
||||
Matt S Trout <mstrout@cpan.org>
|
||||
|
||||
=back
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2006 by Infinity Interactive, Inc.
|
||||
|
||||
This is free software; you can redistribute it and/or modify it under
|
||||
the same terms as the Perl 5 programming language system itself.
|
||||
|
||||
=cut
|
||||
204
CPAN/Moose/Manual/Support.pod
Normal file
204
CPAN/Moose/Manual/Support.pod
Normal file
@@ -0,0 +1,204 @@
|
||||
# PODNAME: Moose::Manual::Support
|
||||
# ABSTRACT: Policies regarding support, releases, and compatibility.
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Moose::Manual::Support - Policies regarding support, releases, and compatibility.
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 2.2207
|
||||
|
||||
=head1 SUPPORT POLICY
|
||||
|
||||
There are two principles to Moose's policy of supported behavior.
|
||||
|
||||
=over 4
|
||||
|
||||
=item 1.
|
||||
|
||||
Moose favors correctness over everything.
|
||||
|
||||
=item 2.
|
||||
|
||||
Moose supports documented and tested behavior, not accidental behavior or side
|
||||
effects.
|
||||
|
||||
=back
|
||||
|
||||
If a behavior has never been documented or tested, the behavior is
|
||||
I<officially> undefined. Relying upon undocumented and untested behavior is
|
||||
done at your own risk.
|
||||
|
||||
If a behavior is documented or tested but found to be incorrect later, the
|
||||
behavior will go through a deprecation period. During the deprecation period,
|
||||
use of that feature will cause a warning. Eventually, the deprecated feature
|
||||
will be removed.
|
||||
|
||||
In some cases, it is not possible to deprecate a behavior. In this case, the
|
||||
behavior will simply be changed in a major release.
|
||||
|
||||
=head1 RELEASE SCHEDULE
|
||||
|
||||
Moose is on a system of quarterly major releases, with minor releases as
|
||||
needed between major releases. A minor release is defined as one that makes
|
||||
every attempt to preserve backwards compatibility. Currently this means that we
|
||||
did not introduce any new dependency conflicts, and that we did not make any
|
||||
changes to documented or tested behavior (this typically means that minor
|
||||
releases will not change any existing tests in the test suite, although they
|
||||
can add new ones). A minor release can include new features and bug fixes.
|
||||
|
||||
Major releases may be backwards incompatible. Moose prioritizes
|
||||
correctness over backwards compatibility or performance; see the L<DEPRECATION
|
||||
POLICY> to understand how backwards incompatible changes are announced.
|
||||
|
||||
Major releases are scheduled to happen during fixed release windows. If the
|
||||
window is missed, then there will not be a major release until the next
|
||||
release window. The release windows are one month long, and occur during the
|
||||
months of January, April, July, and October.
|
||||
|
||||
Before a major release, a series of development releases will be made so that
|
||||
users can test the upcoming major release before it is distributed to CPAN. It
|
||||
is in the best interests of everyone involved if these releases are tested as
|
||||
widely as possible.
|
||||
|
||||
=head1 DEPRECATION POLICY
|
||||
|
||||
Moose has always prioritized correctness over performance and backwards
|
||||
compatibility.
|
||||
|
||||
Major deprecations or API changes are documented in the Changes file as well
|
||||
as in L<Moose::Manual::Delta>. The Moose developers will also make an effort
|
||||
to warn users of upcoming deprecations and breakage through the Moose blog
|
||||
(http://blog.moose.perl.org).
|
||||
|
||||
Deprecated APIs will be preserved for at least one year I<after the major
|
||||
release which deprecates that API>. Deprecated APIs will only be removed in a
|
||||
major release.
|
||||
|
||||
Moose will also warn during installation if the version of Moose being
|
||||
installed will break an installed dependency. Unfortunately, due to the nature
|
||||
of the Perl install process these warnings may be easy to miss.
|
||||
|
||||
=head1 BACKWARDS COMPATIBILITY
|
||||
|
||||
We try to ensure compatibility by having a extensive test suite (last count
|
||||
over 18000 tests), as well as testing a number of packages (currently just
|
||||
under 100 packages) that depend on Moose before any release.
|
||||
|
||||
The current list of downstream dependencies that are tested is in
|
||||
C<xt/author/test-my-dependents.t>.
|
||||
|
||||
=head1 VERSION NUMBERS
|
||||
|
||||
Moose version numbers consist of three parts, in the form X.YYZZ. The X is the
|
||||
"special magic number" that only gets changed for really big changes. Think of
|
||||
this as being like the "5" in Perl 5.12.1.
|
||||
|
||||
The YY portion is the major version number. Moose uses even numbers for stable
|
||||
releases, and odd numbers for trial releases. The ZZ is the minor version, and
|
||||
it simply increases monotonically. It starts at "00" each time a new major
|
||||
version is released.
|
||||
|
||||
Semantically, this means that any two releases which share a major version
|
||||
should be API-compatible with each other. In other words, 2.0200, 2.0201, and
|
||||
2.0274 are all API-compatible.
|
||||
|
||||
Prior to version 2.0, Moose version numbers were monotonically incrementing
|
||||
two decimal values (0.01, 0.02, ... 1.11, 1.12, etc.).
|
||||
|
||||
Moose was declared production ready at version 0.18 (via L<<
|
||||
http://www.perlmonks.org/?node_id=608144 >>).
|
||||
|
||||
=head1 PERL VERSION COMPATIBILITY
|
||||
|
||||
As of version 2.16, Moose will officially support being run on perl 5.10.1+. Our
|
||||
current policy is to support the earliest version of Perl shipped in the latest
|
||||
stable release of any major operating system (this tends to mean CentOS). We
|
||||
will provide at least six months notice (two major releases) when we decide to
|
||||
increase the officially supported Perl version.
|
||||
|
||||
"Officially supported" does not mean that these are the only versions of Perl
|
||||
that Moose will work with. Our declared perl dependency will remain at 5.8.3
|
||||
as long as our test suite continues to pass on 5.8.3. What this does mean is
|
||||
that the core Moose dev team will not be spending any time fixing bugs on
|
||||
versions that aren't officially supported, and new contributions will not be
|
||||
rejected due to being incompatible with older versions of perl except in the
|
||||
most trivial of cases. We will, however, still welcome patches to make Moose
|
||||
compatible with earlier versions, if other people are still interested in
|
||||
maintaining compatibility. As such, the current minimum required version of
|
||||
5.8.3 will remain for as long as downstream users are happy to assist with
|
||||
maintenance.
|
||||
|
||||
Note that although performance regressions are acceptable in order to maintain
|
||||
backwards compatibility (as long as they only affect the older versions),
|
||||
functionality changes and buggy behavior will not be. If it becomes impossible
|
||||
to provide identical functionality between modern Perl versions and
|
||||
unsupported Perl versions, we will increase our declared perl dependency
|
||||
instead.
|
||||
|
||||
=head1 CONTRIBUTING
|
||||
|
||||
Moose has an open contribution policy. Anybody is welcome to submit a
|
||||
patch. Please see L<Moose::Manual::Contributing> for more details.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
Stevan Little <stevan@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=item *
|
||||
|
||||
Jesse Luehrs <doy@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Shawn M Moore <sartak@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
|
||||
|
||||
=item *
|
||||
|
||||
Karen Etheridge <ether@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Florian Ragwitz <rafl@debian.org>
|
||||
|
||||
=item *
|
||||
|
||||
Hans Dieter Pearcey <hdp@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Chris Prather <chris@prather.org>
|
||||
|
||||
=item *
|
||||
|
||||
Matt S Trout <mstrout@cpan.org>
|
||||
|
||||
=back
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2006 by Infinity Interactive, Inc.
|
||||
|
||||
This is free software; you can redistribute it and/or modify it under
|
||||
the same terms as the Perl 5 programming language system itself.
|
||||
|
||||
=cut
|
||||
501
CPAN/Moose/Manual/Types.pod
Normal file
501
CPAN/Moose/Manual/Types.pod
Normal file
@@ -0,0 +1,501 @@
|
||||
# PODNAME: Moose::Manual::Types
|
||||
# ABSTRACT: Moose's type system
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Moose::Manual::Types - Moose's type system
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 2.2207
|
||||
|
||||
=head1 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
|
||||
I<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.
|
||||
|
||||
=head1 THE TYPES
|
||||
|
||||
The basic Moose type hierarchy looks like this
|
||||
|
||||
Any
|
||||
Item
|
||||
Bool
|
||||
Maybe[`a]
|
||||
Undef
|
||||
Defined
|
||||
Value
|
||||
Str
|
||||
Num
|
||||
Int
|
||||
ClassName
|
||||
RoleName
|
||||
Ref
|
||||
ScalarRef[`a]
|
||||
ArrayRef[`a]
|
||||
HashRef[`a]
|
||||
CodeRef
|
||||
RegexpRef
|
||||
GlobRef
|
||||
FileHandle
|
||||
Object
|
||||
|
||||
In practice, the only difference between C<Any> and C<Item> is
|
||||
conceptual. C<Item> is used as the top-level type in the hierarchy.
|
||||
|
||||
The rest of these types correspond to existing Perl concepts.
|
||||
In particular:
|
||||
|
||||
=over 4
|
||||
|
||||
=item
|
||||
|
||||
C<Bool> accepts C<1> for true, and undef, 0, or the empty string as false.
|
||||
|
||||
=item
|
||||
|
||||
C<Maybe[`a]> accepts either C<`a> or C<undef>.
|
||||
|
||||
=item
|
||||
|
||||
C<Num> accepts integers, floating point numbers (both in decimal notation &
|
||||
exponential notation), 0, .0, 0.0 etc. It doesn't accept numbers with
|
||||
whitespace, Inf, Infinity, "0 but true", NaN & other such strings.
|
||||
|
||||
=item
|
||||
|
||||
C<ClassName> and C<RoleName> accept strings that are either the name of a class or the name of a role. The class/role must already be loaded when the constraint is checked.
|
||||
|
||||
=item
|
||||
|
||||
C<FileHandle> accepts either an L<IO::Handle> object or a builtin perl filehandle (see L<Scalar::Util/openhandle>).
|
||||
|
||||
=item
|
||||
|
||||
C<Object> accepts any blessed reference.
|
||||
|
||||
=back
|
||||
|
||||
The types followed by "[`a]" can be parameterized. So instead of just
|
||||
plain C<ArrayRef> we can say that we want C<ArrayRef[Int]> instead. We
|
||||
can even do something like C<HashRef[ArrayRef[Str]]>.
|
||||
|
||||
The C<Maybe[`a]> type deserves a special mention. Used by itself, it
|
||||
doesn't really mean anything (and is equivalent to C<Item>). When it
|
||||
is parameterized, it means that the value is either C<undef> or the
|
||||
parameterized type. So C<Maybe[Int]> means an integer or C<undef>.
|
||||
|
||||
For more details on the type hierarchy, see
|
||||
L<Moose::Util::TypeConstraints>.
|
||||
|
||||
=head1 WHAT IS A TYPE?
|
||||
|
||||
It's important to realize that types are not classes (or
|
||||
packages). Types are just objects (L<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 C<Num> into the
|
||||
appropriate object.
|
||||
|
||||
However, class names I<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 C<'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 C<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:
|
||||
|
||||
subtype 'ModernDateTime'
|
||||
=> as 'DateTime'
|
||||
=> where { $_->year() >= 1980 }
|
||||
=> message { 'The date you provided is not modern enough' };
|
||||
|
||||
has 'valid_dates' => (
|
||||
is => 'ro',
|
||||
isa => 'ArrayRef[DateTime]',
|
||||
);
|
||||
|
||||
Moose will assume that C<DateTime> is a class name in both of these
|
||||
instances.
|
||||
|
||||
=head1 SUBTYPES
|
||||
|
||||
Moose uses subtypes in its built-in hierarchy. For example, C<Int> is
|
||||
a child of C<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 I<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 L<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" };
|
||||
|
||||
Note that the sugar functions for working with types are all exported
|
||||
by L<Moose::Util::TypeConstraints>.
|
||||
|
||||
=head1 TYPE NAMES
|
||||
|
||||
Type names are global throughout the current Perl
|
||||
interpreter. Internally, Moose maps names to type objects via a
|
||||
L<registry|Moose::Meta::TypeConstraint::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, C<MyApp::Types>, which can be loaded by other classes in your
|
||||
application.
|
||||
|
||||
However, before you do this, you should look at the L<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.
|
||||
|
||||
=head1 COERCION
|
||||
|
||||
A coercion lets you tell Moose to automatically convert one type to another.
|
||||
|
||||
subtype 'ArrayRefOfInts',
|
||||
as 'ArrayRef[Int]';
|
||||
|
||||
coerce 'ArrayRefOfInts',
|
||||
from 'Int',
|
||||
via { [ $_ ] };
|
||||
|
||||
You'll note that we created a subtype rather than coercing C<ArrayRef[Int]>
|
||||
directly. It's a bad idea to add coercions to the raw built in
|
||||
types.
|
||||
|
||||
Coercions are global, just like type names, so a coercion applied to a built
|
||||
in type is seen by all modules using Moose types. This is I<another> reason
|
||||
why it is good to namespace your types.
|
||||
|
||||
Moose will I<never> try to coerce a value unless you explicitly ask for
|
||||
it. This is done by setting the C<coerce> attribute option to a true value:
|
||||
|
||||
package Foo;
|
||||
|
||||
has 'sizes' => (
|
||||
is => 'ro',
|
||||
isa => 'ArrayRefOfInts',
|
||||
coerce => 1,
|
||||
);
|
||||
|
||||
Foo->new( sizes => 42 );
|
||||
|
||||
This code example will do the right thing, and the newly created
|
||||
object will have C<[ 42 ]> as its C<sizes> attribute.
|
||||
|
||||
=head2 Deep coercion
|
||||
|
||||
Deep coercion is the coercion of type parameters for parameterized
|
||||
types. Let's take these types as an example:
|
||||
|
||||
subtype 'HexNum',
|
||||
as 'Str',
|
||||
where { /[a-f0-9]/i };
|
||||
|
||||
coerce 'Int',
|
||||
from 'HexNum',
|
||||
via { hex $_ };
|
||||
|
||||
has 'sizes' => (
|
||||
is => 'ro',
|
||||
isa => 'ArrayRef[Int]',
|
||||
coerce => 1,
|
||||
);
|
||||
|
||||
If we try passing an array reference of hex numbers for the C<sizes>
|
||||
attribute, Moose will not do any coercion.
|
||||
|
||||
However, you can define a set of subtypes to enable coercion between
|
||||
two parameterized types.
|
||||
|
||||
subtype 'ArrayRefOfHexNums',
|
||||
as 'ArrayRef[HexNum]';
|
||||
|
||||
subtype 'ArrayRefOfInts',
|
||||
as 'ArrayRef[Int]';
|
||||
|
||||
coerce 'ArrayRefOfInts',
|
||||
from 'ArrayRefOfHexNums',
|
||||
via { [ map { hex } @{$_} ] };
|
||||
|
||||
Foo->new( sizes => [ 'a1', 'ff', '22' ] );
|
||||
|
||||
Now Moose will coerce the hex numbers to integers.
|
||||
|
||||
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.
|
||||
|
||||
=head1 TYPE UNIONS
|
||||
|
||||
Moose allows you to say that an attribute can be of two or more
|
||||
disparate types. For example, we might allow an C<Object> or
|
||||
C<FileHandle>:
|
||||
|
||||
has 'output' => (
|
||||
is => 'rw',
|
||||
isa => 'Object | FileHandle',
|
||||
);
|
||||
|
||||
Moose actually parses that string and recognizes that you are creating
|
||||
a type union. The C<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 C<print> method:
|
||||
|
||||
duck_type 'CanPrint', [qw(print)];
|
||||
|
||||
We can coerce file handles to an object that satisfies this condition
|
||||
with a simple wrapper class:
|
||||
|
||||
package FHWrapper;
|
||||
|
||||
use Moose;
|
||||
|
||||
has 'handle' => (
|
||||
is => 'rw',
|
||||
isa => 'FileHandle',
|
||||
);
|
||||
|
||||
sub print {
|
||||
my $self = shift;
|
||||
my $fh = $self->handle();
|
||||
|
||||
print {$fh} @_;
|
||||
}
|
||||
|
||||
Now we can define a coercion from C<FileHandle> to our wrapper class:
|
||||
|
||||
coerce 'CanPrint'
|
||||
=> from 'FileHandle'
|
||||
=> via { FHWrapper->new( handle => $_ ) };
|
||||
|
||||
has 'output' => (
|
||||
is => 'rw',
|
||||
isa => 'CanPrint',
|
||||
coerce => 1,
|
||||
);
|
||||
|
||||
This pattern of using a coercion instead of a type union will help
|
||||
make your class internals simpler.
|
||||
|
||||
=head1 TYPE CREATION HELPERS
|
||||
|
||||
The L<Moose::Util::TypeConstraints> module exports a number of helper
|
||||
functions for creating specific kinds of types. These include
|
||||
C<class_type>, C<role_type>, C<maybe_type>, and C<duck_type>. See the
|
||||
docs for details.
|
||||
|
||||
One helper worth noting is C<enum>, which allows you to create a
|
||||
subtype of C<Str> that only allows the specified values:
|
||||
|
||||
enum 'RGB', [qw( red green blue )];
|
||||
|
||||
This creates a type named C<RGB>.
|
||||
|
||||
=head1 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 C<isa> option:
|
||||
|
||||
has 'size' => (
|
||||
is => 'ro',
|
||||
isa => subtype( 'Int' => where { $_ > 0 } ),
|
||||
);
|
||||
|
||||
This is handy when you want to create a one-off type and don't want to
|
||||
"pollute" the global namespace registry.
|
||||
|
||||
=head1 VALIDATING METHOD PARAMETERS
|
||||
|
||||
Moose does not provide any means of validating method
|
||||
parameters. However, there are several MooseX extensions on CPAN which
|
||||
let you do this.
|
||||
|
||||
The simplest and least sugary is L<Params::ValidationCompiler>. This
|
||||
lets you validate a set of named parameters using Moose types:
|
||||
|
||||
use Moose::Util::TypeConstraints qw( find_type_constraint );
|
||||
use Params::ValidationCompiler qw( validation_for );
|
||||
|
||||
{
|
||||
my $validator = validation_for(
|
||||
params => {
|
||||
foo => { type => find_type_constraint('Int') },
|
||||
bar => {
|
||||
type => find_type_constraint('Str'),
|
||||
optional => 1,
|
||||
},
|
||||
baz => {
|
||||
type => find_type_constraint('Int'),
|
||||
default => 42,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
sub foo {
|
||||
my %args = $validator->(@_);
|
||||
}
|
||||
}
|
||||
|
||||
L<Params::ValidationCompiler> also supports coercions.
|
||||
|
||||
There are several more powerful extensions that support method parameter
|
||||
validation using Moose types, including L<Moops>, which gives you a full-blown
|
||||
C<method> keyword.
|
||||
|
||||
method morning ( Str $name ) {
|
||||
$self->say("Good morning ${name}!");
|
||||
}
|
||||
|
||||
=head1 LOAD ORDER ISSUES
|
||||
|
||||
Because Moose types are defined at runtime, you may run into load
|
||||
order problems. In particular, you may want to use a class's type
|
||||
constraint before that type has been defined.
|
||||
|
||||
In order to ameliorate this problem, we recommend defining I<all> of your
|
||||
custom types in one module, C<MyApp::Types>, and then loading this module in
|
||||
all of your other modules.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
Stevan Little <stevan@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=item *
|
||||
|
||||
Jesse Luehrs <doy@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Shawn M Moore <sartak@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
|
||||
|
||||
=item *
|
||||
|
||||
Karen Etheridge <ether@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Florian Ragwitz <rafl@debian.org>
|
||||
|
||||
=item *
|
||||
|
||||
Hans Dieter Pearcey <hdp@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Chris Prather <chris@prather.org>
|
||||
|
||||
=item *
|
||||
|
||||
Matt S Trout <mstrout@cpan.org>
|
||||
|
||||
=back
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2006 by Infinity Interactive, Inc.
|
||||
|
||||
This is free software; you can redistribute it and/or modify it under
|
||||
the same terms as the Perl 5 programming language system itself.
|
||||
|
||||
=cut
|
||||
386
CPAN/Moose/Manual/Unsweetened.pod
Normal file
386
CPAN/Moose/Manual/Unsweetened.pod
Normal file
@@ -0,0 +1,386 @@
|
||||
# PODNAME: Moose::Manual::Unsweetened
|
||||
# ABSTRACT: Moose idioms in plain old Perl 5 without the sugar
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=encoding UTF-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Moose::Manual::Unsweetened - Moose idioms in plain old Perl 5 without the sugar
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
version 2.2207
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
If you're trying to figure out just what the heck Moose does, and how
|
||||
it saves you time, you might find it helpful to see what Moose is
|
||||
I<really> doing for you. This document shows you the translation from
|
||||
Moose sugar back to plain old Perl 5.
|
||||
|
||||
=head1 CLASSES AND ATTRIBUTES
|
||||
|
||||
First, we define two very small classes the Moose way.
|
||||
|
||||
package Person;
|
||||
|
||||
use DateTime;
|
||||
use DateTime::Format::Natural;
|
||||
use Moose;
|
||||
use Moose::Util::TypeConstraints;
|
||||
|
||||
has name => (
|
||||
is => 'rw',
|
||||
isa => 'Str',
|
||||
required => 1,
|
||||
);
|
||||
|
||||
# Moose doesn't know about non-Moose-based classes.
|
||||
class_type 'DateTime';
|
||||
|
||||
my $en_parser = DateTime::Format::Natural->new(
|
||||
lang => 'en',
|
||||
time_zone => 'UTC',
|
||||
);
|
||||
|
||||
coerce 'DateTime'
|
||||
=> from 'Str'
|
||||
=> via { $en_parser->parse_datetime($_) };
|
||||
|
||||
has birth_date => (
|
||||
is => 'rw',
|
||||
isa => 'DateTime',
|
||||
coerce => 1,
|
||||
handles => { birth_year => 'year' },
|
||||
);
|
||||
|
||||
enum 'ShirtSize' => [qw( s m l xl xxl )];
|
||||
|
||||
has shirt_size => (
|
||||
is => 'rw',
|
||||
isa => 'ShirtSize',
|
||||
default => 'l',
|
||||
);
|
||||
|
||||
This is a fairly simple class with three attributes. We also define an enum
|
||||
type to validate t-shirt sizes because we don't want to end up with something
|
||||
like "blue" for the shirt size!
|
||||
|
||||
package User;
|
||||
|
||||
use Email::Valid;
|
||||
use Moose;
|
||||
use Moose::Util::TypeConstraints;
|
||||
|
||||
extends 'Person';
|
||||
|
||||
subtype 'Email'
|
||||
=> as 'Str'
|
||||
=> where { Email::Valid->address($_) }
|
||||
=> message { "$_ is not a valid email address" };
|
||||
|
||||
has email_address => (
|
||||
is => 'rw',
|
||||
isa => 'Email',
|
||||
required => 1,
|
||||
);
|
||||
|
||||
This class subclasses Person to add a single attribute, email address.
|
||||
|
||||
Now we will show what these classes would look like in plain old Perl
|
||||
5. For the sake of argument, we won't use any base classes or any
|
||||
helpers like C<Class::Accessor>.
|
||||
|
||||
package Person;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Carp qw( confess );
|
||||
use DateTime;
|
||||
use DateTime::Format::Natural;
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my %p = ref $_[0] ? %{ $_[0] } : @_;
|
||||
|
||||
exists $p{name}
|
||||
or confess 'name is a required attribute';
|
||||
$class->_validate_name( $p{name} );
|
||||
|
||||
exists $p{birth_date}
|
||||
or confess 'birth_date is a required attribute';
|
||||
|
||||
$p{birth_date} = $class->_coerce_birth_date( $p{birth_date} );
|
||||
$class->_validate_birth_date( $p{birth_date} );
|
||||
|
||||
$p{shirt_size} = 'l'
|
||||
unless exists $p{shirt_size};
|
||||
|
||||
$class->_validate_shirt_size( $p{shirt_size} );
|
||||
|
||||
return bless \%p, $class;
|
||||
}
|
||||
|
||||
sub _validate_name {
|
||||
shift;
|
||||
my $name = shift;
|
||||
|
||||
local $Carp::CarpLevel = $Carp::CarpLevel + 1;
|
||||
|
||||
defined $name
|
||||
or confess 'name must be a string';
|
||||
}
|
||||
|
||||
{
|
||||
my $en_parser = DateTime::Format::Natural->new(
|
||||
lang => 'en',
|
||||
time_zone => 'UTC',
|
||||
);
|
||||
|
||||
sub _coerce_birth_date {
|
||||
shift;
|
||||
my $date = shift;
|
||||
|
||||
return $date unless defined $date && ! ref $date;
|
||||
|
||||
my $dt = $en_parser->parse_datetime($date);
|
||||
|
||||
return $dt ? $dt : undef;
|
||||
}
|
||||
}
|
||||
|
||||
sub _validate_birth_date {
|
||||
shift;
|
||||
my $birth_date = shift;
|
||||
|
||||
local $Carp::CarpLevel = $Carp::CarpLevel + 1;
|
||||
|
||||
$birth_date->isa('DateTime')
|
||||
or confess 'birth_date must be a DateTime object';
|
||||
}
|
||||
|
||||
sub _validate_shirt_size {
|
||||
shift;
|
||||
my $shirt_size = shift;
|
||||
|
||||
local $Carp::CarpLevel = $Carp::CarpLevel + 1;
|
||||
|
||||
defined $shirt_size
|
||||
or confess 'shirt_size cannot be undef';
|
||||
|
||||
my %sizes = map { $_ => 1 } qw( s m l xl xxl );
|
||||
|
||||
$sizes{$shirt_size}
|
||||
or confess "$shirt_size is not a valid shirt size (s, m, l, xl, xxl)";
|
||||
}
|
||||
|
||||
sub name {
|
||||
my $self = shift;
|
||||
|
||||
if (@_) {
|
||||
$self->_validate_name( $_[0] );
|
||||
$self->{name} = $_[0];
|
||||
}
|
||||
|
||||
return $self->{name};
|
||||
}
|
||||
|
||||
sub birth_date {
|
||||
my $self = shift;
|
||||
|
||||
if (@_) {
|
||||
my $date = $self->_coerce_birth_date( $_[0] );
|
||||
$self->_validate_birth_date( $date );
|
||||
|
||||
$self->{birth_date} = $date;
|
||||
}
|
||||
|
||||
return $self->{birth_date};
|
||||
}
|
||||
|
||||
sub birth_year {
|
||||
my $self = shift;
|
||||
|
||||
return $self->birth_date->year;
|
||||
}
|
||||
|
||||
sub shirt_size {
|
||||
my $self = shift;
|
||||
|
||||
if (@_) {
|
||||
$self->_validate_shirt_size( $_[0] );
|
||||
$self->{shirt_size} = $_[0];
|
||||
}
|
||||
|
||||
return $self->{shirt_size};
|
||||
}
|
||||
|
||||
Wow, that was a mouthful! One thing to note is just how much space the
|
||||
data validation code consumes. As a result, it's pretty common for
|
||||
Perl 5 programmers to just not bother. Unfortunately, not validating
|
||||
arguments leads to surprises down the line ("why is birth_date an
|
||||
email address?").
|
||||
|
||||
Also, did you spot the (intentional) bug?
|
||||
|
||||
It's in the C<_validate_birth_date()> method. We should check that
|
||||
the value in C<$birth_date> is actually defined and an object before
|
||||
we go and call C<isa()> on it! Leaving out those checks means our data
|
||||
validation code could actually cause our program to die. Oops.
|
||||
|
||||
Note that if we add a superclass to Person we'll have to change the
|
||||
constructor to account for that.
|
||||
|
||||
(As an aside, getting all the little details of what Moose does for
|
||||
you just right in this example was really not easy, which emphasizes
|
||||
the point of the example. Moose saves you a lot of work!)
|
||||
|
||||
Now let's see User:
|
||||
|
||||
package User;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Carp qw( confess );
|
||||
use Email::Valid;
|
||||
use Scalar::Util qw( blessed );
|
||||
|
||||
use parent 'Person';
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my %p = ref $_[0] ? %{ $_[0] } : @_;
|
||||
|
||||
exists $p{email_address}
|
||||
or confess 'email_address is a required attribute';
|
||||
$class->_validate_email_address( $p{email_address} );
|
||||
|
||||
my $self = $class->SUPER::new(%p);
|
||||
|
||||
$self->{email_address} = $p{email_address};
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub _validate_email_address {
|
||||
shift;
|
||||
my $email_address = shift;
|
||||
|
||||
local $Carp::CarpLevel = $Carp::CarpLevel + 1;
|
||||
|
||||
defined $email_address
|
||||
or confess 'email_address must be a string';
|
||||
|
||||
Email::Valid->address($email_address)
|
||||
or confess "$email_address is not a valid email address";
|
||||
}
|
||||
|
||||
sub email_address {
|
||||
my $self = shift;
|
||||
|
||||
if (@_) {
|
||||
$self->_validate_email_address( $_[0] );
|
||||
$self->{email_address} = $_[0];
|
||||
}
|
||||
|
||||
return $self->{email_address};
|
||||
}
|
||||
|
||||
That one was shorter, but it only has one attribute.
|
||||
|
||||
Between the two classes, we have a whole lot of code that doesn't do
|
||||
much. We could probably simplify this by defining some sort of
|
||||
"attribute and validation" hash, like this:
|
||||
|
||||
package Person;
|
||||
|
||||
my %Attr = (
|
||||
name => {
|
||||
required => 1,
|
||||
validate => sub { defined $_ },
|
||||
},
|
||||
birth_date => {
|
||||
required => 1,
|
||||
validate => sub { blessed $_ && $_->isa('DateTime') },
|
||||
},
|
||||
shirt_size => {
|
||||
required => 1,
|
||||
validate => sub { defined $_ && $_ =~ /^(?:s|m|l|xl|xxl)$/i },
|
||||
}
|
||||
);
|
||||
|
||||
Then we could define a base class that would accept such a definition
|
||||
and do the right thing. Keep that sort of thing up and we're well on
|
||||
our way to writing a half-assed version of Moose!
|
||||
|
||||
Of course, there are CPAN modules that do some of what Moose does,
|
||||
like C<Class::Accessor>, C<Class::Meta>, and so on. But none of them
|
||||
put together all of Moose's features along with a layer of declarative
|
||||
sugar, nor are these other modules designed for extensibility in the
|
||||
same way as Moose. With Moose, it's easy to write a MooseX module to
|
||||
replace or extend a piece of built-in functionality.
|
||||
|
||||
Moose is a complete OO package in and of itself, and is part of a rich
|
||||
ecosystem of extensions. It also has an enthusiastic community of
|
||||
users and is being actively maintained and developed.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
Stevan Little <stevan@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Dave Rolsky <autarch@urth.org>
|
||||
|
||||
=item *
|
||||
|
||||
Jesse Luehrs <doy@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Shawn M Moore <sartak@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
|
||||
|
||||
=item *
|
||||
|
||||
Karen Etheridge <ether@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Florian Ragwitz <rafl@debian.org>
|
||||
|
||||
=item *
|
||||
|
||||
Hans Dieter Pearcey <hdp@cpan.org>
|
||||
|
||||
=item *
|
||||
|
||||
Chris Prather <chris@prather.org>
|
||||
|
||||
=item *
|
||||
|
||||
Matt S Trout <mstrout@cpan.org>
|
||||
|
||||
=back
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
This software is copyright (c) 2006 by Infinity Interactive, Inc.
|
||||
|
||||
This is free software; you can redistribute it and/or modify it under
|
||||
the same terms as the Perl 5 programming language system itself.
|
||||
|
||||
=cut
|
||||
Reference in New Issue
Block a user