Rename Basics::Recipe9 to Basics::Genome_OverloadingSubtypesAndCoercion
[gitmo/Moose.git] / lib / Moose / Cookbook / Basics / Recipe10.pod
1 package Moose::Cookbook::Basics::Recipe10;
2
3 # ABSTRACT: Using BUILDARGS and BUILD to hook into object construction
4
5 __END__
6
7
8 =pod
9
10 =head1 SYNOPSIS
11
12   package Person;
13
14   has 'ssn' => (
15       is        => 'ro',
16       isa       => 'Str',
17       predicate => 'has_ssn',
18   );
19
20   has 'country_of_residence' => (
21       is      => 'ro',
22       isa     => 'Str',
23       default => 'usa'
24   );
25
26   has 'first_name' => (
27       is  => 'ro',
28       isa => 'Str',
29   );
30
31   has 'last_name' => (
32       is  => 'ro',
33       isa => 'Str',
34   );
35
36   around BUILDARGS => sub {
37       my $orig = shift;
38       my $class = shift;
39
40       if ( @_ == 1 && ! ref $_[0] ) {
41           return $class->$orig(ssn => $_[0]);
42       }
43       else {
44           return $class->$orig(@_);
45       }
46   };
47
48   sub BUILD {
49       my $self = shift;
50
51       if ( $self->country_of_residence eq 'usa' ) {
52           die 'Cannot create a Person who lives in the USA without an ssn.'
53               unless $self->has_ssn;
54       }
55   }
56
57 =head1 DESCRIPTION
58
59 This recipe demonstrates the use of C<BUILDARGS> and C<BUILD>. By
60 defining these methods, we can hook into the object construction
61 process without overriding C<new>.
62
63 The C<BUILDARGS> method is called I<before> an object has been
64 created. It is called as a class method, and receives all of the
65 parameters passed to the C<new> method. It is expected to do something
66 with these arguments and return a hash reference. The keys of the hash
67 must be attribute C<init_arg>s.
68
69 The primary purpose of C<BUILDARGS> is to allow a class to accept
70 something other than named arguments. In the case of our C<Person>
71 class, we are allowing it to be called with a single argument, a
72 social security number:
73
74   my $person = Person->new('123-45-6789');
75
76 The key part of our C<BUILDARGS> is this conditional:
77
78       if ( @_ == 1 && ! ref $_[0] ) {
79           return $class->$orig(ssn => $_[0]);
80       }
81
82 By default, Moose constructors accept a list of key-value pairs, or a
83 hash reference. We need to make sure that C<$_[0]> is not a reference
84 before assuming it is a social security number.
85
86 We call the original C<BUILDARGS> method to handle all the other
87 cases. You should always do this in your own C<BUILDARGS> methods,
88 since L<Moose::Object> provides its own C<BUILDARGS> method that
89 handles hash references and a list of key-value pairs.
90
91 The C<BUILD> method is called I<after> the object is constructed, but
92 before it is returned to the caller. The C<BUILD> method provides an
93 opportunity to check the object state as a whole. This is a good place
94 to put logic that cannot be expressed as a type constraint on a single
95 attribute.
96
97 In the C<Person> class, we need to check the relationship between two
98 attributes, C<ssn> and C<country_of_residence>. We throw an exception
99 if the object is not logically consistent.
100
101 =head1 MORE CONSIDERATIONS
102
103 This recipe is made significantly simpler because all of the
104 attributes are read-only. If the C<country_of_residence> attribute
105 were settable, we would need to check that a Person had an C<ssn> if
106 the new country was C<usa>. This could be done with a C<before>
107 modifier.
108
109 =head1 CONCLUSION
110
111 We have repeatedly discouraged overriding C<new> in Moose
112 classes. This recipe shows how you can use C<BUILDARGS> and C<BUILD>
113 to hook into object construction without overriding C<new>.
114
115 The C<BUILDARGS> method lets us expand on Moose's built-in parameter
116 handling for constructors. The C<BUILD> method lets us implement
117 logical constraints across the whole object after it is created.
118
119 =cut