From: Dave Rolsky Date: Fri, 12 Dec 2008 21:19:02 +0000 (+0000) Subject: Checking in the first chunk of the Attributes manual section X-Git-Tag: 0.66~27^2~32 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=8d38e631864cd10b10a1eedafb82270f3942252c;p=gitmo%2FMoose.git Checking in the first chunk of the Attributes manual section --- diff --git a/lib/Moose/Manual/Attributes.pod b/lib/Moose/Manual/Attributes.pod new file mode 100644 index 0000000..58cd3c6 --- /dev/null +++ b/lib/Moose/Manual/Attributes.pod @@ -0,0 +1,323 @@ +=pod + +=head1 NAME + +Moose::Manual::Attribute - Object attributes with Moose + +=head1 INTRODUCTION + +Attributes are the most feature-rich part of Moose, and also one of +the most useful. It's easy to imagine a class without roles or method +modifiers, but almost every class has attributes. + +Attributes are properties that every member of a class has. For +example, we might say that "every Person object has a first name and +last name. Attributes can be optional, so that we can say "some Person +objects have a social security number (and some don't)". + +At its simplest, an attribute can be thought of slot in hash that can +be read and set. However, attributes, can also have things like +default values, laziness, type constraints, delegation and much more. + +=head1 ATTRIBUTE 101 + +Use the C function to declare an attribute: + + package Person; + + use Moose; + + has 'first_name' => ( is => 'rw' ); + +This says that all person objects have an optional "first_name" +attribute that can be both read and set on the object. + +=head2 Read-write Vs Read-only + +The code inside the parentheses defines the details of the +attribute. There are a lot of options you can put here, but in the +simplest form you just need to include C, which can be either +C (read-write) or C (read-only). + +(In fact, you could even omit C, but that leaves you with an +attribute that has no accessors, which is pointless unless you're +doing some deep, dark magic). + +=head2 Accessor Methods + +Each attribute has one or more accessor methods. An accessor lets you +read and write the value of the 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 +accessor. Simple. + +So with our Person example above, we now have a single C +accessor that can set or return a person object's first name. + +If you want, you can also explicitly specify the method names to be +used for getting and setting an attribute's value. This is +particularly handy when you'd like an attribute to be publically +readable, but only privately settable. For example: + + has 'weight' => + ( is => 'rw', + 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 +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 getting and +setting, even when setting is a public method. In I, Damian Conway recommends that getter methods start with +"get_" and setter methods start with "set_". + +We can do exactly that by providing names for both the C and +C 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 do things like override the default +accessor method conventions. See L for more +details. + +=head2 Predicate and Clearer Methods + +Moose is able to explicitly distinguish between false or undefined +values, and an attribute which is not set. If you want to be able to +access and manipulate these states, you also need to define clearer +and predicate methods for your attributes. + +A predicate method can be used to determine whether or not a given +attribute is currently set. Note that even if the attribute was +explicitly set to undef or some other false value, 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 +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 + +Note that by default, Moose does not make a predicate or clearer for +you. You have to explicitly provide a method name for the ones you +want. + +=head2 Required or Not? + +By default, all attributes are optional. That means that they do not +need to be provided at object construction time. If you want to make +an attribute required, simply set the required option to true: + + has 'name' => + ( is => 'rw', + required => 1, + ); + +There are a couple caveats worth mentioning in regards to what +required actually means. + +Basically, all it says is that this attribute must be provided to the +constructor. 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 though something is defined as required, you can +remove it after object construction. + +So if you do make an attribute required, that probably means that +providing a clearer doesn't make much sense. In some cases, it might +be handy to have a I clearer and predicate for a required +attribute. + +=head2 Default and Builder Methods + +Attributes can have default values, and there are several ways to +specify this. + +In the simplest form, you simply provide a non-reference scalar value +for the "default" option: + + has 'size' => + ( is => 'rw', + default => 'medium', + predicate => 'has_size', + ); + +If the size attribute is not provided to the constructor, then it ends +up being set to "medium": + + my $person = Person->new(); + $person->size; # medium + $person->has_size; # true + +You can also provide a subroutine reference for default. This +reference will be called a method on the object. + + has 'size' => + ( is => 'rw', + default => + sub { ('small', 'medium', 'large')[ int( rand 3 ) ] }, + predicate => 'has_size', + ); + +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 before +other attributes have been set. If your default is dependent on other +parts of the object's state, you can make the default lazy, which 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: + + has 'mapping' => + ( is => 'rw', + default => {}, # wrong! + ); + +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! + ); + +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 builder method for your attribute: + + has 'size' => + ( is => 'rw', + 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, the C<_build_size> method can be overridden in +subclasses. + +We strongly recommend that you use a builder instead of a default for +anything beyond the most trivial default. + +=head2 Laziness and lazy_build + +Moose lets you defer attribute population by making an attribute lazy: + + has 'size' => + ( is => 'rw', + lazy => 1, + builder => '_build_size', + ); + +When the lazy option is true, the attribute is not populated 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 be lazy. During object +construction, default subroutine references are not called in any +particular order, so you cannot count on other attribute being +populated at that time. + +Second, there's often no reason to spend program time calculating a +default before its needed. Making an attribute lazy lets you defer the +cost until the attribute is needed. If the attribute is I +needed, you save some CPU time. + +We recommend that you make any attribute with a builder or non-trivial +default lazy 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 (_), 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. The lazy_build simply +prepends the attribute name with "_build_" to come up with the builder +name. + +=head2 Private Attributes