X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FMoose%2FManual%2FAttributes.pod;h=66d9364718db5ffe9e43f50889e805b5b58ff2f4;hb=d18b8cb5559067c64a65a66a0604d787091abf3d;hp=e62842c09b7ddd4087fe1cbe7d8bf5d2aca00deb;hpb=6c384d50e6b130170aadd3496d0ef5275a5333d9;p=gitmo%2FMoose.git diff --git a/lib/Moose/Manual/Attributes.pod b/lib/Moose/Manual/Attributes.pod index e62842c..66d9364 100644 --- a/lib/Moose/Manual/Attributes.pod +++ b/lib/Moose/Manual/Attributes.pod @@ -1,8 +1,10 @@ -=pod +package Moose::Manual::Attributes; + +# ABSTRACT: Object attributes with Moose -=head1 NAME +__END__ -Moose::Manual::Attributes - Object attributes with Moose +=pod =head1 INTRODUCTION @@ -36,16 +38,21 @@ Use the C function to declare an attribute: This says that all C objects have an optional read-write "first_name" attribute. -=head2 Read-write Vs read-only +=head2 Read-write vs. read-only -The options passed to C define the properties of the -attribute. There are a many options, but in the simplest form you just -need to set C, which can be either C (read-write) or C -(read-only). +The options passed to C define the properties of the attribute. There are +many options, but in the simplest form you just need to set C, which can +be either C (read-only) or C (read-write). When an attribute is C, +you can change it by passing a value to its accessor. When an attribute is +C, you may only read the current value of the attribute. -(In fact, you could even omit C, but that gives you an attribute -that has no accessors, which is pointless unless you're doing some -deep, dark magic). +In fact, you could even omit C, but that gives you an attribute +that has no accessor. This can be useful with other attribute options, +such as C. However, if your attribute generates I +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 to C. =head2 Accessor methods @@ -54,7 +61,7 @@ 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 then your accessor will be -read-only. If you declared it read-write, you get a read-write +read-only. If you declared it as C, you get a read-write accessor. Simple. Given our C example above, we now have a single C @@ -67,12 +74,12 @@ particularly handy when you'd like an attribute to be publicly readable, but only privately settable. For example: has 'weight' => ( - is => 'rw', + is => 'ro', writer => '_set_weight', ); -This might be useful if weight is calculated based on other methods, -for example every time the C method is called, we might adjust +This might be useful if weight is calculated based on other methods. +For example, every time the C 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. @@ -91,7 +98,7 @@ C methods: 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 override the default naming +extension system that lets you override the default naming conventions. See L for more details. =head2 Predicate and clearer methods @@ -102,8 +109,9 @@ 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 an attribute can be explicitly set to C or -some other false value, but the predicate will return true. +currently set. Note that an attribute can be explicitly set to +C or some other false value, but the predicate will return +true. The clearer method unsets the attribute. This is I the same as setting the value to C, but you can only distinguish @@ -142,8 +150,9 @@ predicate, and clearer method. 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. +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? @@ -152,16 +161,16 @@ provided at object construction time. If you want to make an attribute required, simply set the C option to true: has 'name' => ( - is => 'rw', + 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) must be provided -to the constructor. It does not say anything about its value, so it -could be C. +Basically, all it says is that this attribute (C) must be provided to +the constructor, or be lazy with either a default or a builder. It does not +say anything about its value, so it could be C. If you define a clearer method on a required attribute, the clearer I work, so even a required attribute can be unset after object @@ -181,7 +190,7 @@ In the simplest form, you simply provide a non-reference scalar value for the C option: has 'size' => ( - is => 'rw', + is => 'ro', default => 'medium', predicate => 'has_size', ); @@ -197,27 +206,45 @@ You can also provide a subroutine reference for C. This reference will be called as a method on the object. has 'size' => ( - is => 'rw', + is => 'ro', default => sub { ( 'small', 'medium', 'large' )[ int( rand 3 ) ] }, predicate => 'has_size', ); -This is dumb example, but it illustrates the point that the subroutine +This is a trivial example, but it illustrates the point that the subroutine will be called for every new object created. -Of course, if it's 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. Laziness is covered in the next section. +When you provide a C 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 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. 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. This is necessary because otherwise -Perl would instantiate the reference exactly once, and it would be -shared by all objects: +must return it from a subroutine. has 'mapping' => ( - is => 'rw', + 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! ); @@ -226,20 +253,15 @@ 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: - - has 'mapping' => ( - is => 'rw', - default => sub { {} }, # right! - ); +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 instead -supply a C method for your attribute: +As an alternative to using a subroutine reference, you can supply a C +method for your attribute: has 'size' => ( - is => 'rw', + is => 'ro', builder => '_build_size', predicate => 'has_size', ); @@ -248,21 +270,64 @@ supply a C method for your attribute: 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, the C<_build_size> method can be overridden in -subclasses. +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 method, it can be subclassed or provided by a role. We strongly recommend that you use a C instead of a C for anything beyond the most trivial default. -=head2 Laziness and C +A C, just like a C, is called as a method on the +object with no additional parameters. + +=head3 Builders allow subclassing + +Because the C is called I, it goes through Perl's +method resolution. This means that builder methods are both +inheritable and overridable. + +If we subclass our C 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: + + 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. + +=head2 Laziness Moose lets you defer attribute population by making an attribute C: has 'size' => ( - is => 'rw', + is => 'ro', lazy => 1, builder => '_build_size', ); @@ -285,58 +350,6 @@ some CPU time. We recommend that you make any attribute with a builder or non-trivial default C as a matter of course. -To facilitate this, you can simply specify the C attribute -option. This bundles up a number of options together: - - has 'size' => ( - is => 'rw', - lazy_build => 1, - ); - -This is the same as specifying all of these options: - - has 'size' => ( - is => 'rw', - lazy => 1, - builder => '_build_size', - clearer => 'clear_size', - predicate => 'has_size', - ); - -If your attribute name starts with an underscore (C<_>), then the clearer -and predicate will as well: - - has '_size' => ( - is => 'rw', - lazy_build => 1, - ); - -becomes: - - has '_size' => ( - is => 'rw', - lazy => 1, - builder => '_build__size', - clearer => '_clear_size', - predicate => '_has_size', - ); - -Note the doubled underscore in the builder name. Internally, Moose -simply prepends the attribute name with "_build_" to come up with the -builder name. - -If you don't like the names that C generates, you can -always provide your own: - - has 'size' => ( - is => 'rw', - lazy_build => 1, - clearer => '_clear_size', - ); - -Options that you explicitly provide are always used in favor of -Moose's internal defaults. - =head2 Constructor parameters (C) By default, each attribute can be passed by name to the class's @@ -344,10 +357,10 @@ 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. -Both of these goals can be accomplished with the C option: +You can do either of these things with the C option: has 'bigness' => ( - is => 'rw', + is => 'ro', init_arg => 'size', ); @@ -358,9 +371,10 @@ 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 => 'rw', - lazy_build => 1, - init_arg => undef, + is => 'ro', + lazy => 1, + builder => '_build_genetic_code', + init_arg => undef, ); By setting the C to C, we make it impossible to set @@ -382,6 +396,15 @@ C whenever the attribute is set: This is very useful when you're building objects that may contain circular references. +When the object in a weak references goes out of scope, the attribute's value +will become C "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 is a subroutine that is called whenever the attribute is @@ -393,26 +416,39 @@ set: ); sub _size_set { - my ( $self, $size, $meta_attr ) = @_; + my ( $self, $size, $old_size ) = @_; - warn $self->name, " size is now $size\n"; + my $msg = $self->name; + + if ( @_ > 2 ) { + $msg .= " - old size was $old_size"; + } + + $msg .= " - size is now $size"; + warn $msg; } -The trigger is called as a method, and receives the new value as well -as the L object for the attribute. The trigger -is called I the value is set. +The trigger is called I 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. -This differs from an after method modifier in two ways. First, a +This differs from an C method modifier in two ways. First, a trigger is only called when the attribute is set, as opposed to -whenever the accessor is called. Second, it is also called if the -attribute is set via a lazy default or builder. +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 called when an attribute is populated +from a C or C. =head2 Attribute types Attributes can be restricted to only accept certain types: has 'first_name' => ( - is => 'rw', + is => 'ro', isa => 'Str', ); @@ -431,10 +467,10 @@ discussion of Moose's type system. =head2 Delegation -Attributes can define methods which simply delegate to their values: +An attribute can define methods which simply delegate to its value: has 'hair_color' => ( - is => 'rw', + is => 'ro', isa => 'Graphics::Color::RGB', handles => { hair_color_hex => 'as_hex_string' }, ); @@ -446,31 +482,17 @@ $self->hair_color->as_hex_string >>. See L for documentation on how to set up delegation methods. -=head2 Metaclass and traits +=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 custom metaclasses and metaclass traits. +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. -When declaring an attribute, you can declare a metaclass or a set of -traits for the attribute: - - use MooseX::AttributeHelpers; - - has 'mapping' => ( - metaclass => 'Collection::Hash', - is => 'ro', - default => sub { {} }, - ); - -In this case, the metaclass C really refers to -L. - -You can also apply one or more traits to an attribute: +You can apply one or more traits to an attribute: use MooseX::MetaDescription; has 'size' => ( - is => 'rw', + is => 'ro', traits => ['MooseX::MetaDescription::Meta::Trait'], description => { html_widget => 'text_input', @@ -486,37 +508,36 @@ attribute metaclasses and traits. See L for some examples. You can also write your own metaclasses and traits. See the "Meta" and "Extending" recipes in L for examples. -=head1 ATTRIBUTE INHERITANCE - -By default, a child inherits all of its parent class(es)' attributes -as-is. However, you can explicitly change some aspects of the -inherited attribute in the child class. - -The options that can be overridden in a subclass are: - -=over 4 - -=item * default - -=item * coerce - -=item * required - -=item * documentation - -=item * lazy - -=item * isa - -=item * handles - -=item * builder +=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, C, C, C, 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', + }, + ); -=item * metaclass +See L for more details. -=item * traits +=head1 ATTRIBUTE INHERITANCE -=back +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 override an attribute, you simply prepend its name with a plus sign (C<+>): @@ -538,12 +559,30 @@ to C<'Bill'>. We recommend that you exercise caution when changing the type (C) of an inherited attribute. +=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 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 of their aspects. We recommend that you read the -L and L documents to -get a more complete understanding of attribute features. +aspects. We recommend that you read the L +and L documents to get a more complete +understanding of attribute features. =head1 A FEW MORE OPTIONS @@ -567,37 +606,23 @@ it. If your attribute is an array reference or hash reference, the C option will make Moose dereference the value when it is -returned from the reader method: +returned from the reader method I: my %map = $object->mapping; This option only works if your attribute is explicitly typed as an -C or C. +C or C. When the reader is called in I context, +the reference itself is returned. -However, we recommend that you use L for -these types of attributes, which gives you much more control over how -they are accessed and manipulated. +However, we recommend that you use L traits +for these types of attributes, which gives you much more control over how +they are accessed and manipulated. See also +L. =head2 Initializer -Moose provides an attribute option called C. This is -similar to C, except that it is I called during object -construction. - -This option is inherited from L, but we recommend that you -use a C (which is Moose-only) instead. - -=head1 AUTHOR - -Dave Rolsky Eautarch@urth.orgE - -=head1 COPYRIGHT AND LICENSE - -Copyright 2009 by Infinity Interactive, Inc. - -L - -This library is free software; you can redistribute it and/or modify -it under the same terms as Perl itself. +Moose provides an attribute option called C. This is called when +the attribute's value is being set in the constructor, and lets you change the +value before it is set. =cut