stop closing over the method metaobject
[gitmo/Moose.git] / lib / Moose / Manual / Delegation.pod
CommitLineData
daa0fd7d 1package Moose::Manual::Delegation;
2
3# ABSTRACT: Attribute delegation
093a09aa 4
daa0fd7d 5__END__
093a09aa 6
daa0fd7d 7=pod
093a09aa 8
9=head1 WHAT IS DELEGATION?
10
54c97a15 11Delegation is a feature that lets you create "proxy" methods that do nothing
12more than call some other method on an attribute. This lets you simplify a
13complex set of "has-a" relationships and present a single unified API from one
14class.
093a09aa 15
d3e02c74 16With delegation, consumers of a class don't need to know about all the
17objects it contains, reducing the amount of API they need to learn.
093a09aa 18
19Delegations are defined as a mapping between one or more methods
20provided by the "real" class (the delegatee), and a set of
21corresponding methods in the delegating class. The delegating class
d3e02c74 22can re-use the method names provided by the delegatee or provide its
093a09aa 23own names.
24
25Delegation is also a great way to wrap an existing class, especially a
26non-Moose class or one that is somehow hard (or impossible) to
27subclass.
28
29=head1 DEFINING A MAPPING
30
31Moose offers a number of options for defining a delegation's mapping,
32ranging from simple to complex.
33
34The simplest form is to simply specify a list of methods:
35
36 package Website;
37
38 use Moose;
39
40 has 'uri' => (
41 is => 'ro',
42 isa => 'URI',
43 handles => [qw( host path )],
44 );
45
46With this definition, we can call C<< $website->host >> and it "just
47works". Under the hood, Moose will call C<< $website->uri->host >> for
b3b5ff5a 48you. Note that C<$website> is not automatically passed to the C<host>
49method; the invocant is C<< $website->uri >>.
093a09aa 50
51We can also define a mapping as a hash reference. This allows you to
52rename methods as part of the mapping:
53
54 package Website;
55
56 use Moose;
57
58 has 'uri' => (
59 is => 'ro',
60 isa => 'URI',
61 handles => {
62 hostname => 'host',
63 path => 'path',
64 },
65 );
66
67In this example, we've created a C<< $website->hostname >> method,
68rather than using C<URI.pm>'s name, C<host>.
69
70These two mapping forms are the ones you will use most often. The
54c97a15 71remaining methods are a bit more complex.
093a09aa 72
73 has 'uri' => (
74 is => 'ro',
75 isa => 'URI',
76 handles => qr/^(?:host|path|query.*)/,
77 );
78
79This is similar to the array version, except it uses the regex to
80match against all the methods provided by the delegatee. In order for
81this to work, you must provide an C<isa> parameter for the attribute,
82and it must be a class. Moose uses this to introspect the delegatee
83class and determine what methods it provides.
84
85You can use a role name as the value of C<handles>:
86
87 has 'uri' => (
88 is => 'ro',
89 isa => 'URI',
90 handles => 'HasURI',
91 );
92
93Moose will introspect the role to determine what methods it provides
94and create a mapping for each of those methods.
95
96Finally, you can also provide a sub reference to I<generate> a
97mapping. You probably won't need this version often (if ever). See the
98L<Moose> docs for more details on exactly how this works.
99
e132fd56 100=head1 NATIVE DELEGATION
50f346d7 101
e132fd56 102Native delegations allow you to delegate to standard Perl data structures as
103if they were objects.
f4c5daeb 104
50f346d7 105 has 'queue' => (
f4c5daeb 106 traits => ['Array'],
54c97a15 107 isa => 'ArrayRef[Item]',
50f346d7 108 default => sub { [ ] },
109 handles => {
f4c5daeb 110 add_item => 'push',
50f346d7 111 next_item => 'shift',
9610c1d2 112 },
50f346d7 113 )
114
e132fd56 115The C<Array> trait in the C<traits> parameter tells Moose that you would like
116to use the set of Array helpers. Moose will then create C<add_item> and
117C<next_item> methods that "just work". Behind the scenes C<add_item> is
118something like
50f346d7 119
f4c5daeb 120 sub add_item {
50f346d7 121 my ($self, @items) = @_;
26366034 122
f4c5daeb 123 for my $item (@items) {
124 $Item_TC->validate($item);
125 }
26366034 126
50f346d7 127 push @{ $self->queue }, @items;
128 }
129
e132fd56 130Moose includes the following traits for native delegation:
54c97a15 131
132=over 4
133
134=item * L<Array|Moose::Meta::Attribute::Native::Trait::Array>
135
136=item * L<Bool|Moose::Meta::Attribute::Native::Trait::Bool>
137
138=item * L<Code|Moose::Meta::Attribute::Native::Trait::Code>
139
140=item * L<Counter|Moose::Meta::Attribute::Native::Trait::Counter>
141
142=item * L<Hash|Moose::Meta::Attribute::Native::Trait::Hash>
143
144=item * L<Number|Moose::Meta::Attribute::Native::Trait::Number>
145
146=item * L<String|Moose::Meta::Attribute::Native::Trait::String>
147
148=back
50f346d7 149
150=head1 CURRYING
151
54c97a15 152Currying allows you to create a method with some pre-set parameters. You can
153create a curried delegation method:
50f346d7 154
155 package Spider;
156 use Moose;
157
158 has request => (
26366034 159 is => 'ro'
160 isa => 'HTTP::Request',
50f346d7 161 handles => {
26366034 162 set_user_agent => [ header => 'UserAgent' ],
9610c1d2 163 },
50f346d7 164 )
165
8580644d 166With this definition, calling C<< $spider->set_user_agent('MyClient') >> will
54c97a15 167call C<< $spider->request->header('UserAgent', 'MyClient') >> behind the
168scenes.
169
8da1f3d8 170Note that with currying, the currying always starts with the first parameter to
013181e1 171a method (C<$_[0]>). Any arguments you pass to the delegation come after the
54c97a15 172curried arguments.
50f346d7 173
093a09aa 174=head1 MISSING ATTRIBUTES
175
176It is perfectly valid to delegate methods to an attribute which is not
d3e02c74 177required or can be undefined. When a delegated method is called, Moose
178will throw a runtime error if the attribute does not contain an
179object.
093a09aa 180
093a09aa 181=cut