bump version to 0.82
[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
403cfbec 10our $VERSION = '0.82';
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
e9497117 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 {
c7e28c19 61 Carp::cluck('The initialize_body method has been made private.'
62 . " The public version is deprecated and will be removed in a future release.\n");
d5c7f638 63 shift->_initialize_body;
e9497117 64}
65
66sub _initialize_body {
ba38bf08 67 my $self = shift;
8d2d4c67 68
ba38bf08 69 my $method_name = join "_" => (
afc92ac6 70 '_generate',
8d2d4c67 71 $self->accessor_type,
ba38bf08 72 'method',
d90b42a6 73 ($self->is_inline ? 'inline' : ())
ba38bf08 74 );
8d2d4c67 75
a6eef5a3 76 eval { $self->{'body'} = $self->$method_name() };
77 die $@ if $@;
ba38bf08 78}
79
80## generators
81
82sub generate_accessor_method {
c7e28c19 83 Carp::cluck('The generate_accessor_method method has been made private.'
84 . " The public version is deprecated and will be removed in a future release.\n");
d5c7f638 85 shift->_generate_accessor_method;
afc92ac6 86}
87
88sub _generate_accessor_method {
8d2d4c67 89 my $attr = (shift)->associated_attribute;
ba38bf08 90 return sub {
91 $attr->set_value($_[0], $_[1]) if scalar(@_) == 2;
92 $attr->get_value($_[0]);
93 };
94}
95
96sub generate_reader_method {
c7e28c19 97 Carp::cluck('The generate_reader_method method has been made private.'
98 . " The public version is deprecated and will be removed in a future release.\n");
d5c7f638 99 shift->_generate_reader_method;
afc92ac6 100}
101
102sub _generate_reader_method {
8d2d4c67 103 my $attr = (shift)->associated_attribute;
104 return sub {
ba38bf08 105 confess "Cannot assign a value to a read-only accessor" if @_ > 1;
106 $attr->get_value($_[0]);
8d2d4c67 107 };
ba38bf08 108}
109
110sub generate_writer_method {
c7e28c19 111 Carp::cluck('The generate_writer_method method has been made private.'
112 . " The public version is deprecated and will be removed in a future release.\n");
d5c7f638 113 shift->_generate_writer_method;
afc92ac6 114}
115
116sub _generate_writer_method {
8d2d4c67 117 my $attr = (shift)->associated_attribute;
ba38bf08 118 return sub {
119 $attr->set_value($_[0], $_[1]);
120 };
121}
122
123sub generate_predicate_method {
c7e28c19 124 Carp::cluck('The generate_predicate_method method has been made private.'
125 . " The public version is deprecated and will be removed in a future release.\n");
d5c7f638 126 shift->_generate_predicate_method;
afc92ac6 127}
128
129sub _generate_predicate_method {
8d2d4c67 130 my $attr = (shift)->associated_attribute;
131 return sub {
3545c727 132 $attr->has_value($_[0])
ba38bf08 133 };
134}
135
136sub generate_clearer_method {
c7e28c19 137 Carp::cluck('The generate_clearer_method method has been made private.'
138 . " The public version is deprecated and will be removed in a future release.\n");
d5c7f638 139 shift->_generate_clearer_method;
afc92ac6 140}
141
142sub _generate_clearer_method {
8d2d4c67 143 my $attr = (shift)->associated_attribute;
144 return sub {
3545c727 145 $attr->clear_value($_[0])
ba38bf08 146 };
147}
148
149## Inline methods
150
ba38bf08 151sub generate_accessor_method_inline {
c7e28c19 152 Carp::cluck('The generate_accessor_method_inline method has been made private.'
153 . " The public version is deprecated and will be removed in a future release.\n");
d5c7f638 154 shift->_generate_accessor_method_inline;
afc92ac6 155}
156
157sub _generate_accessor_method_inline {
7f8de9b4 158 my $self = shift;
159 my $attr = $self->associated_attribute;
ba38bf08 160 my $attr_name = $attr->name;
161 my $meta_instance = $attr->associated_class->instance_metaclass;
162
a6eef5a3 163 my $code = $self->_eval_closure(
0c6f3280 164 {},
7f8de9b4 165 'sub {'
a71a4ccb 166 . $meta_instance->inline_set_slot_value('$_[0]', $attr_name, '$_[1]')
7f8de9b4 167 . ' if scalar(@_) == 2; '
a71a4ccb 168 . $meta_instance->inline_get_slot_value('$_[0]', $attr_name)
7f8de9b4 169 . '}'
170 );
a6eef5a3 171 confess "Could not generate inline accessor because : $@" if $@;
172
173 return $code;
ba38bf08 174}
175
176sub generate_reader_method_inline {
c7e28c19 177 Carp::cluck('The generate_reader_method_inline method has been made private.'
178 . " The public version is deprecated and will be removed in a future release.\n");
d5c7f638 179 shift->_generate_reader_method_inline;
afc92ac6 180}
181
182sub _generate_reader_method_inline {
7f8de9b4 183 my $self = shift;
184 my $attr = $self->associated_attribute;
ba38bf08 185 my $attr_name = $attr->name;
186 my $meta_instance = $attr->associated_class->instance_metaclass;
187
a6eef5a3 188 my $code = $self->_eval_closure(
0c6f3280 189 {},
7f8de9b4 190 'sub {'
ba38bf08 191 . 'confess "Cannot assign a value to a read-only accessor" if @_ > 1;'
e9a19694 192 . $meta_instance->inline_get_slot_value('$_[0]', $attr_name)
7f8de9b4 193 . '}'
194 );
a6eef5a3 195 confess "Could not generate inline reader because : $@" if $@;
196
197 return $code;
ba38bf08 198}
199
200sub generate_writer_method_inline {
c7e28c19 201 Carp::cluck('The generate_writer_method_inline method has been made private.'
202 . " The public version is deprecated and will be removed in a future release.\n");
d5c7f638 203 shift->_generate_writer_method_inline;
afc92ac6 204}
205
206sub _generate_writer_method_inline {
7f8de9b4 207 my $self = shift;
208 my $attr = $self->associated_attribute;
ba38bf08 209 my $attr_name = $attr->name;
210 my $meta_instance = $attr->associated_class->instance_metaclass;
211
a6eef5a3 212 my $code = $self->_eval_closure(
0c6f3280 213 {},
7f8de9b4 214 'sub {'
e9a19694 215 . $meta_instance->inline_set_slot_value('$_[0]', $attr_name, '$_[1]')
7f8de9b4 216 . '}'
217 );
a6eef5a3 218 confess "Could not generate inline writer because : $@" if $@;
219
220 return $code;
ba38bf08 221}
222
ba38bf08 223sub generate_predicate_method_inline {
c7e28c19 224 Carp::cluck('The generate_predicate_method_inline method has been made private.'
225 . " The public version is deprecated and will be removed in a future release.\n");
d5c7f638 226 shift->_generate_predicate_method_inline;
afc92ac6 227}
228
229sub _generate_predicate_method_inline {
7f8de9b4 230 my $self = shift;
231 my $attr = $self->associated_attribute;
ba38bf08 232 my $attr_name = $attr->name;
233 my $meta_instance = $attr->associated_class->instance_metaclass;
234
a6eef5a3 235 my $code = $self->_eval_closure(
0c6f3280 236 {},
7f8de9b4 237 'sub {'
e9a19694 238 . $meta_instance->inline_is_slot_initialized('$_[0]', $attr_name)
7f8de9b4 239 . '}'
240 );
a6eef5a3 241 confess "Could not generate inline predicate because : $@" if $@;
242
243 return $code;
ba38bf08 244}
245
246sub generate_clearer_method_inline {
c7e28c19 247 Carp::cluck('The generate_clearer_method_inline method has been made private.'
248 . " The public version is deprecated and will be removed in a future release.\n");
d5c7f638 249 shift->_generate_clearer_method_inline;
afc92ac6 250}
251
252sub _generate_clearer_method_inline {
7f8de9b4 253 my $self = shift;
254 my $attr = $self->associated_attribute;
ba38bf08 255 my $attr_name = $attr->name;
256 my $meta_instance = $attr->associated_class->instance_metaclass;
257
a6eef5a3 258 my $code = $self->_eval_closure(
0c6f3280 259 {},
7f8de9b4 260 'sub {'
e9a19694 261 . $meta_instance->inline_deinitialize_slot('$_[0]', $attr_name)
7f8de9b4 262 . '}'
263 );
a6eef5a3 264 confess "Could not generate inline clearer because : $@" if $@;
265
266 return $code;
ba38bf08 267}
268
2691;
270
271__END__
272
273=pod
274
8d2d4c67 275=head1 NAME
ba38bf08 276
277Class::MOP::Method::Accessor - Method Meta Object for accessors
278
279=head1 SYNOPSIS
280
96e38ba6 281 use Class::MOP::Method::Accessor;
282
283 my $reader = Class::MOP::Method::Accessor->new(
284 attribute => $attribute,
285 is_inline => 1,
286 accessor_type => 'reader',
287 );
8d2d4c67 288
b7045e66 289 $reader->body->execute($instance); # call the reader method
ba38bf08 290
291=head1 DESCRIPTION
292
1385ad9d 293This is a subclass of <Class::MOP::Method> which is used by
294C<Class::MOP::Attribute> to generate accessor code. It handles
295generation of readers, writers, predicates and clearers. For each type
296of method, it can either create a subroutine reference, or actually
297inline code by generating a string and C<eval>'ing it.
96e38ba6 298
ba38bf08 299=head1 METHODS
300
301=over 4
302
1385ad9d 303=item B<< Class::MOP::Method::Accessor->new(%options) >>
ba38bf08 304
1385ad9d 305This returns a new C<Class::MOP::Method::Accessor> based on the
306C<%options> provided.
96e38ba6 307
308=over 4
309
9258c369 310=item * attribute
96e38ba6 311
1385ad9d 312This is the C<Class::MOP::Attribute> for which accessors are being
313generated. This option is required.
96e38ba6 314
9258c369 315=item * accessor_type
96e38ba6 316
1385ad9d 317This is a string which should be one of "reader", "writer",
318"accessor", "predicate", or "clearer". This is the type of method
319being generated. This option is required.
96e38ba6 320
9258c369 321=item * is_inline
96e38ba6 322
1385ad9d 323This indicates whether or not the accessor should be inlined. This
cb8d08c6 324defaults to false.
96e38ba6 325
9258c369 326=item * name
327
328The method name (without a package name). This is required.
329
330=item * package_name
331
332The package name for the method. This is required.
333
96e38ba6 334=back
ba38bf08 335
1385ad9d 336=item B<< $metamethod->accessor_type >>
ba38bf08 337
1385ad9d 338Returns the accessor type which was passed to C<new>.
96e38ba6 339
1385ad9d 340=item B<< $metamethod->is_inline >>
ba38bf08 341
1385ad9d 342Returns a boolean indicating whether or not the accessor is inlined.
96e38ba6 343
1385ad9d 344=item B<< $metamethod->associated_attribute >>
ba38bf08 345
1385ad9d 346This returns the L<Class::MOP::Attribute> object which was passed to
347C<new>.
96e38ba6 348
1385ad9d 349=item B<< $metamethod->body >>
96e38ba6 350
1385ad9d 351The method itself is I<generated> when the accessor object is
352constructed.
ba38bf08 353
354=back
355
356=head1 AUTHORS
357
358Stevan Little E<lt>stevan@iinteractive.comE<gt>
359
ba38bf08 360=head1 COPYRIGHT AND LICENSE
361
070bb6c9 362Copyright 2006-2009 by Infinity Interactive, Inc.
ba38bf08 363
364L<http://www.iinteractive.com>
365
366This library is free software; you can redistribute it and/or modify
8d2d4c67 367it under the same terms as Perl itself.
ba38bf08 368
369=cut
370