From: Dave Rolsky Date: Tue, 17 Feb 2009 15:41:43 +0000 (+0000) Subject: Add basics recipe 11, BUILD & BUILDARGS X-Git-Tag: 0.71~15 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=04d80e2a40cb02740dea7def17777cc0eb27d3d4;p=gitmo%2FMoose.git Add basics recipe 11, BUILD & BUILDARGS --- diff --git a/lib/Moose/Cookbook.pod b/lib/Moose/Cookbook.pod index 030af86..9940871 100644 --- a/lib/Moose/Cookbook.pod +++ b/lib/Moose/Cookbook.pod @@ -75,9 +75,10 @@ provide a default attribute value. Demonstrates using operator overloading, coercion, and subtypes to model how eye color is determined during reproduction. -=item L - BUILD and BUILDARGS (TODO) +=item L - Using BUILDARGS and BUILD to hook into object construction -We need a good recipe demonstrating how these work. +This recipe demonstrates the use of C and C to hook +into object construction. =back diff --git a/lib/Moose/Cookbook/Basics/Recipe11.pod b/lib/Moose/Cookbook/Basics/Recipe11.pod new file mode 100644 index 0000000..4c36c80 --- /dev/null +++ b/lib/Moose/Cookbook/Basics/Recipe11.pod @@ -0,0 +1,129 @@ + +=pod + +=head1 NAME + +Moose::Cookbook::Basics::Recipe11 - Using BUILDARGS and BUILD to hook into object construction + +=head1 SYNOPSIS + + package Person; + + has 'ssn' => ( + is => 'ro', + isa => 'Str', + predicate => 'has_ssn', + ); + + has 'country_of_residence' => ( + is => 'ro', + isa => 'Str', + default => 'usa' + ); + + has 'first_name' => ( + is => 'ro', + isa => 'Str', + ); + + has 'last_name' => ( + is => 'ro', + isa => 'Str', + ); + + sub BUILDARGS { + my $class = shift; + + if ( @_ == 1 && ! ref $_[0] ) { + return { ssn => $_[0] }; + } + else { + return $class->SUPER::BUILDARGS(@_); + } + } + + sub BUILD { + my $self = shift; + + if ( $self->country_of_residence eq 'usa' ) { + die 'Cannot create a Person who lives in the USA without an ssn.' + unless $self->has_ssn; + } + } + +=head1 DESCRIPTION + +This recipe demonstrates the use of C and C. By +defining these methods, we can hook into the object construction +process without overriding C. + +The C method is called I an object has been +created. It is called as a class method, and receives all of the +parameters passed to the C method. It is expected to do something +with these arguments and return a hash reference. The keys of the hash +must be attribute Cs. + +The primary purpose of C is to allow a class to accept +something other than named arguments. In the case of our C +class, we are allowing it to be called with a single argument, a +social security number: + + my $person = Person->new('123-45-6789'); + +The key part of our C is this conditional: + + if ( @_ == 1 && ! ref $_[0] ) { + return { ssn => $_[0] }; + } + +By default, Moose constructors accept a list of key-value pairs, or a +hash reference. We need to make sure that C<$_[0]> is not a reference +before assuming it is a social security number. + +We call C<< $class->SUPER::BUILDARGS(@_) >> to handle all the other +cases. You should always do this in your own C methods, +since L provides its own C method that +handles hash references and a list of key-value pairs. + +The C method is called I the object is constructed, but +before it is returned to the caller. The C method provides an +opportunity to check the object state as a whole. This is a good place +to put logic that cannot be expressed as a type constraint on a single +object. + +In the C class, we need to check the relationship between two +attributes, C and C. We throw an exception +if the object is not logically consistent. + +=head1 MORE CONSIDERATIONS + +This recipe is made significantly simpler because all of the +attributes are read-only. If the C attribute +were settable, we would need to check that a Person had an C if +the new country was C. This could be done with a C +modifier. + +=head1 CONCLUSION + +We have repeatedly discouraged overriding C in Moose +classes. This recipe shows how you can use C and C +to hook into object construction without overriding C + +The C method lets us expand on Moose's built-in parameter +handling for constructors. The C method lets us implement +logical constraints across the whole object after it is created. + +=head1 AUTHOR + +Dave Rolsky Eautarch@urth.orgE + +=head1 COPYRIGHT AND LICENSE + +Copyright 2006-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. + +=cut