docs for CMOP::Method::Accessor
[gitmo/Class-MOP.git] / lib / Class / MOP / Method / Accessor.pm
CommitLineData
ba38bf08 1
2package Class::MOP::Method::Accessor;
3
4use strict;
5use warnings;
6
7use Carp 'confess';
8use Scalar::Util 'blessed', 'weaken';
9
eca95e04 10our $VERSION = '0.78';
d519662a 11$VERSION = eval $VERSION;
ba38bf08 12our $AUTHORITY = 'cpan:STEVAN';
13
565f0cbb 14use base 'Class::MOP::Method::Generated';
ba38bf08 15
ba38bf08 16sub new {
17 my $class = shift;
18 my %options = @_;
8d2d4c67 19
ba38bf08 20 (exists $options{attribute})
21 || confess "You must supply an attribute to construct with";
8d2d4c67 22
ba38bf08 23 (exists $options{accessor_type})
8d2d4c67 24 || confess "You must supply an accessor_type to construct with";
25
ba38bf08 26 (blessed($options{attribute}) && $options{attribute}->isa('Class::MOP::Attribute'))
8d2d4c67 27 || confess "You must supply an attribute which is a 'Class::MOP::Attribute' instance";
28
b38f3848 29 ($options{package_name} && $options{name})
32202ce2 30 || confess "You must supply the package_name and name parameters $Class::MOP::Method::UPGRADE_ERROR_TEXT";
b38f3848 31
0bfc85b8 32 my $self = $class->_new(\%options);
8d2d4c67 33
34 # we don't want this creating
35 # a cycle in the code, if not
ba38bf08 36 # needed
8683db0e 37 weaken($self->{'attribute'});
8d2d4c67 38
565f0cbb 39 $self->initialize_body;
8d2d4c67 40
ba38bf08 41 return $self;
42}
43
a9e38dc7 44sub _new {
0bfc85b8 45 my $class = shift;
46 my $options = @_ == 1 ? $_[0] : {@_};
a9e38dc7 47
0bfc85b8 48 $options->{is_inline} ||= 0;
a9e38dc7 49
0bfc85b8 50 return bless $options, $class;
a9e38dc7 51}
52
ba38bf08 53## accessors
54
8683db0e 55sub associated_attribute { (shift)->{'attribute'} }
56sub accessor_type { (shift)->{'accessor_type'} }
ba38bf08 57
8d2d4c67 58## factory
ba38bf08 59
565f0cbb 60sub initialize_body {
ba38bf08 61 my $self = shift;
8d2d4c67 62
ba38bf08 63 my $method_name = join "_" => (
8d2d4c67 64 'generate',
65 $self->accessor_type,
ba38bf08 66 'method',
d90b42a6 67 ($self->is_inline ? 'inline' : ())
ba38bf08 68 );
8d2d4c67 69
a6eef5a3 70 eval { $self->{'body'} = $self->$method_name() };
71 die $@ if $@;
ba38bf08 72}
73
74## generators
75
76sub generate_accessor_method {
8d2d4c67 77 my $attr = (shift)->associated_attribute;
ba38bf08 78 return sub {
79 $attr->set_value($_[0], $_[1]) if scalar(@_) == 2;
80 $attr->get_value($_[0]);
81 };
82}
83
84sub generate_reader_method {
8d2d4c67 85 my $attr = (shift)->associated_attribute;
86 return sub {
ba38bf08 87 confess "Cannot assign a value to a read-only accessor" if @_ > 1;
88 $attr->get_value($_[0]);
8d2d4c67 89 };
ba38bf08 90}
91
92sub generate_writer_method {
8d2d4c67 93 my $attr = (shift)->associated_attribute;
ba38bf08 94 return sub {
95 $attr->set_value($_[0], $_[1]);
96 };
97}
98
99sub generate_predicate_method {
8d2d4c67 100 my $attr = (shift)->associated_attribute;
101 return sub {
3545c727 102 $attr->has_value($_[0])
ba38bf08 103 };
104}
105
106sub generate_clearer_method {
8d2d4c67 107 my $attr = (shift)->associated_attribute;
108 return sub {
3545c727 109 $attr->clear_value($_[0])
ba38bf08 110 };
111}
112
113## Inline methods
114
115
116sub generate_accessor_method_inline {
7f8de9b4 117 my $self = shift;
118 my $attr = $self->associated_attribute;
ba38bf08 119 my $attr_name = $attr->name;
120 my $meta_instance = $attr->associated_class->instance_metaclass;
121
a6eef5a3 122 my $code = $self->_eval_closure(
0c6f3280 123 {},
7f8de9b4 124 'sub {'
a71a4ccb 125 . $meta_instance->inline_set_slot_value('$_[0]', $attr_name, '$_[1]')
7f8de9b4 126 . ' if scalar(@_) == 2; '
a71a4ccb 127 . $meta_instance->inline_get_slot_value('$_[0]', $attr_name)
7f8de9b4 128 . '}'
129 );
a6eef5a3 130 confess "Could not generate inline accessor because : $@" if $@;
131
132 return $code;
ba38bf08 133}
134
135sub generate_reader_method_inline {
7f8de9b4 136 my $self = shift;
137 my $attr = $self->associated_attribute;
ba38bf08 138 my $attr_name = $attr->name;
139 my $meta_instance = $attr->associated_class->instance_metaclass;
140
a6eef5a3 141 my $code = $self->_eval_closure(
0c6f3280 142 {},
7f8de9b4 143 'sub {'
ba38bf08 144 . 'confess "Cannot assign a value to a read-only accessor" if @_ > 1;'
e9a19694 145 . $meta_instance->inline_get_slot_value('$_[0]', $attr_name)
7f8de9b4 146 . '}'
147 );
a6eef5a3 148 confess "Could not generate inline reader because : $@" if $@;
149
150 return $code;
ba38bf08 151}
152
153sub generate_writer_method_inline {
7f8de9b4 154 my $self = shift;
155 my $attr = $self->associated_attribute;
ba38bf08 156 my $attr_name = $attr->name;
157 my $meta_instance = $attr->associated_class->instance_metaclass;
158
a6eef5a3 159 my $code = $self->_eval_closure(
0c6f3280 160 {},
7f8de9b4 161 'sub {'
e9a19694 162 . $meta_instance->inline_set_slot_value('$_[0]', $attr_name, '$_[1]')
7f8de9b4 163 . '}'
164 );
a6eef5a3 165 confess "Could not generate inline writer because : $@" if $@;
166
167 return $code;
ba38bf08 168}
169
170
171sub generate_predicate_method_inline {
7f8de9b4 172 my $self = shift;
173 my $attr = $self->associated_attribute;
ba38bf08 174 my $attr_name = $attr->name;
175 my $meta_instance = $attr->associated_class->instance_metaclass;
176
a6eef5a3 177 my $code = $self->_eval_closure(
0c6f3280 178 {},
7f8de9b4 179 'sub {'
e9a19694 180 . $meta_instance->inline_is_slot_initialized('$_[0]', $attr_name)
7f8de9b4 181 . '}'
182 );
a6eef5a3 183 confess "Could not generate inline predicate because : $@" if $@;
184
185 return $code;
ba38bf08 186}
187
188sub generate_clearer_method_inline {
7f8de9b4 189 my $self = shift;
190 my $attr = $self->associated_attribute;
ba38bf08 191 my $attr_name = $attr->name;
192 my $meta_instance = $attr->associated_class->instance_metaclass;
193
a6eef5a3 194 my $code = $self->_eval_closure(
0c6f3280 195 {},
7f8de9b4 196 'sub {'
e9a19694 197 . $meta_instance->inline_deinitialize_slot('$_[0]', $attr_name)
7f8de9b4 198 . '}'
199 );
a6eef5a3 200 confess "Could not generate inline clearer because : $@" if $@;
201
202 return $code;
ba38bf08 203}
204
2051;
206
207__END__
208
209=pod
210
8d2d4c67 211=head1 NAME
ba38bf08 212
213Class::MOP::Method::Accessor - Method Meta Object for accessors
214
215=head1 SYNOPSIS
216
96e38ba6 217 use Class::MOP::Method::Accessor;
218
219 my $reader = Class::MOP::Method::Accessor->new(
220 attribute => $attribute,
221 is_inline => 1,
222 accessor_type => 'reader',
223 );
8d2d4c67 224
b7045e66 225 $reader->body->execute($instance); # call the reader method
ba38bf08 226
227=head1 DESCRIPTION
228
1385ad9d 229This is a subclass of <Class::MOP::Method> which is used by
230C<Class::MOP::Attribute> to generate accessor code. It handles
231generation of readers, writers, predicates and clearers. For each type
232of method, it can either create a subroutine reference, or actually
233inline code by generating a string and C<eval>'ing it.
96e38ba6 234
ba38bf08 235=head1 METHODS
236
237=over 4
238
1385ad9d 239=item B<< Class::MOP::Method::Accessor->new(%options) >>
ba38bf08 240
1385ad9d 241This returns a new C<Class::MOP::Method::Accessor> based on the
242C<%options> provided.
96e38ba6 243
244=over 4
245
1385ad9d 246=item attribute
96e38ba6 247
1385ad9d 248This is the C<Class::MOP::Attribute> for which accessors are being
249generated. This option is required.
96e38ba6 250
1385ad9d 251=item accessor_type
96e38ba6 252
1385ad9d 253This is a string which should be one of "reader", "writer",
254"accessor", "predicate", or "clearer". This is the type of method
255being generated. This option is required.
96e38ba6 256
1385ad9d 257=item is_inline
96e38ba6 258
1385ad9d 259This indicates whether or not the accessor should be inlined. This
260default to false.
96e38ba6 261
262=back
ba38bf08 263
1385ad9d 264=item B<< $metamethod->accessor_type >>
ba38bf08 265
1385ad9d 266Returns the accessor type which was passed to C<new>.
96e38ba6 267
1385ad9d 268=item B<< $metamethod->is_inline >>
ba38bf08 269
1385ad9d 270Returns a boolean indicating whether or not the accessor is inlined.
96e38ba6 271
1385ad9d 272=item B<< $metamethod->associated_attribute >>
ba38bf08 273
1385ad9d 274This returns the L<Class::MOP::Attribute> object which was passed to
275C<new>.
96e38ba6 276
1385ad9d 277=item B<< $metamethod->body >>
96e38ba6 278
1385ad9d 279The method itself is I<generated> when the accessor object is
280constructed.
ba38bf08 281
282=back
283
284=head1 AUTHORS
285
286Stevan Little E<lt>stevan@iinteractive.comE<gt>
287
ba38bf08 288=head1 COPYRIGHT AND LICENSE
289
070bb6c9 290Copyright 2006-2009 by Infinity Interactive, Inc.
ba38bf08 291
292L<http://www.iinteractive.com>
293
294This library is free software; you can redistribute it and/or modify
8d2d4c67 295it under the same terms as Perl itself.
ba38bf08 296
297=cut
298