X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FMoose%2FManual%2FAttributes.pod;h=174c62413fb4e62139ce3aad56fe15099306eb4d;hb=2de18801c55ae2cfac72d6697e797f3875286d83;hp=011b01f26cfe815f55dbf1294ab1586040b56f2d;hpb=d67ce58f8d57e240ded1f1ebdf262456ce2ff5be;p=gitmo%2FMoose.git diff --git a/lib/Moose/Manual/Attributes.pod b/lib/Moose/Manual/Attributes.pod index 011b01f..174c624 100644 --- a/lib/Moose/Manual/Attributes.pod +++ b/lib/Moose/Manual/Attributes.pod @@ -2,7 +2,7 @@ =head1 NAME -Moose::Manual::Attribute - Object attributes with Moose +Moose::Manual::Attributes - Object attributes with Moose =head1 INTRODUCTION @@ -36,10 +36,10 @@ 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 +attribute. There are many options, but in the simplest form you just need to set C, which can be either C (read-write) or C (read-only). @@ -67,12 +67,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 +91,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 +102,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 @@ -152,16 +153,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 +182,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,7 +198,7 @@ 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', @@ -206,10 +207,22 @@ reference will be called as a method on the object. This is dumb 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 ? 'big' : '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 @@ -217,7 +230,7 @@ Perl would instantiate the reference exactly once, and it would be shared by all objects: has 'mapping' => ( - is => 'rw', + is => 'ro', default => {}, # wrong! ); @@ -229,7 +242,7 @@ end up shared across many objects. Instead, wrap it in a subroutine reference: has 'mapping' => ( - is => 'rw', + is => 'ro', default => sub { {} }, # right! ); @@ -239,7 +252,7 @@ As an alternative to using a subroutine reference, you can instead supply a C method for your attribute: has 'size' => ( - is => 'rw', + is => 'ro', builder => '_build_size', predicate => 'has_size', ); @@ -250,19 +263,62 @@ supply a C method for your attribute: 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. +organization. We strongly recommend that you use a C instead of a C for anything beyond the most trivial default. +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 can be composed from 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 and C Moose lets you defer attribute population by making an attribute C: has 'size' => ( - is => 'rw', + is => 'ro', lazy => 1, builder => '_build_size', ); @@ -289,14 +345,14 @@ To facilitate this, you can simply specify the C attribute option. This bundles up a number of options together: has 'size' => ( - is => 'rw', + is => 'ro', lazy_build => 1, ); This is the same as specifying all of these options: has 'size' => ( - is => 'rw', + is => 'ro', lazy => 1, builder => '_build_size', clearer => 'clear_size', @@ -307,14 +363,14 @@ If your attribute name starts with an underscore (C<_>), then the clearer and predicate will as well: has '_size' => ( - is => 'rw', + is => 'ro', lazy_build => 1, ); becomes: has '_size' => ( - is => 'rw', + is => 'ro', lazy => 1, builder => '_build__size', clearer => '_clear_size', @@ -329,7 +385,7 @@ If you don't like the names that C generates, you can always provide your own: has 'size' => ( - is => 'rw', + is => 'ro', lazy_build => 1, clearer => '_clear_size', ); @@ -347,7 +403,7 @@ unsettable via the constructor. Both of these goals can be accomplished with the C option: has 'bigness' => ( - is => 'rw', + is => 'ro', init_arg => 'size', ); @@ -358,7 +414,7 @@ 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', + is => 'ro', lazy_build => 1, init_arg => undef, ); @@ -393,26 +449,29 @@ set: ); sub _size_set { - my ( $self, $size, $meta_attr ) = @_; + my ( $self, $size ) = @_; warn $self->name, " size is now $size\n"; } -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 as a method, and receives the new value as its argument. +The trigger is called I the value is set. This differs from an after 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', ); @@ -434,7 +493,7 @@ discussion of Moose's type system. Attributes can define methods which simply delegate to their values: has 'hair_color' => ( - is => 'rw', + is => 'ro', isa => 'Graphics::Color::RGB', handles => { hair_color_hex => 'as_hex_string' }, ); @@ -470,7 +529,7 @@ You can also 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', @@ -541,9 +600,9 @@ of an inherited attribute. =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