2 package Class::MOP::Method::Accessor;
8 use Scalar::Util 'blessed', 'weaken';
10 our $VERSION = '0.91';
11 $VERSION = eval $VERSION;
12 our $AUTHORITY = 'cpan:STEVAN';
14 use base 'Class::MOP::Method::Generated';
20 (exists $options{attribute})
21 || confess "You must supply an attribute to construct with";
23 (exists $options{accessor_type})
24 || confess "You must supply an accessor_type to construct with";
26 (blessed($options{attribute}) && $options{attribute}->isa('Class::MOP::Attribute'))
27 || confess "You must supply an attribute which is a 'Class::MOP::Attribute' instance";
29 ($options{package_name} && $options{name})
30 || confess "You must supply the package_name and name parameters $Class::MOP::Method::UPGRADE_ERROR_TEXT";
32 my $self = $class->_new(\%options);
34 # we don't want this creating
35 # a cycle in the code, if not
37 weaken($self->{'attribute'});
39 $self->_initialize_body;
47 return Class::MOP::Class->initialize($class)->new_object(@_)
48 if $class ne __PACKAGE__;
50 my $params = @_ == 1 ? $_[0] : {@_};
53 # inherited from Class::MOP::Method
54 body => $params->{body},
55 associated_metaclass => $params->{associated_metaclass},
56 package_name => $params->{package_name},
57 name => $params->{name},
58 original_method => $params->{original_method},
60 # inherit from Class::MOP::Generated
61 is_inline => $params->{is_inline} || 0,
62 definition_context => $params->{definition_context},
64 # defined in this class
65 attribute => $params->{attribute},
66 accessor_type => $params->{accessor_type},
72 sub associated_attribute { (shift)->{'attribute'} }
73 sub accessor_type { (shift)->{'accessor_type'} }
78 Carp::cluck('The initialize_body method has been made private.'
79 . " The public version is deprecated and will be removed in a future release.\n");
80 shift->_initialize_body;
83 sub _initialize_body {
86 my $method_name = join "_" => (
90 ($self->is_inline ? 'inline' : ())
93 $self->{'body'} = $self->$method_name();
98 sub generate_accessor_method {
99 Carp::cluck('The generate_accessor_method method has been made private.'
100 . " The public version is deprecated and will be removed in a future release.\n");
101 shift->_generate_accessor_method;
104 sub _generate_accessor_method {
105 my $attr = (shift)->associated_attribute;
107 $attr->set_value($_[0], $_[1]) if scalar(@_) == 2;
108 $attr->get_value($_[0]);
112 sub generate_reader_method {
113 Carp::cluck('The generate_reader_method method has been made private.'
114 . " The public version is deprecated and will be removed in a future release.\n");
115 shift->_generate_reader_method;
118 sub _generate_reader_method {
119 my $attr = (shift)->associated_attribute;
121 confess "Cannot assign a value to a read-only accessor" if @_ > 1;
122 $attr->get_value($_[0]);
126 sub generate_writer_method {
127 Carp::cluck('The generate_writer_method method has been made private.'
128 . " The public version is deprecated and will be removed in a future release.\n");
129 shift->_generate_writer_method;
132 sub _generate_writer_method {
133 my $attr = (shift)->associated_attribute;
135 $attr->set_value($_[0], $_[1]);
139 sub generate_predicate_method {
140 Carp::cluck('The generate_predicate_method method has been made private.'
141 . " The public version is deprecated and will be removed in a future release.\n");
142 shift->_generate_predicate_method;
145 sub _generate_predicate_method {
146 my $attr = (shift)->associated_attribute;
148 $attr->has_value($_[0])
152 sub generate_clearer_method {
153 Carp::cluck('The generate_clearer_method method has been made private.'
154 . " The public version is deprecated and will be removed in a future release.\n");
155 shift->_generate_clearer_method;
158 sub _generate_clearer_method {
159 my $attr = (shift)->associated_attribute;
161 $attr->clear_value($_[0])
168 sub _inline_call_trigger {
169 my ($self, $attr, $instance, $value) = @_;
170 return '' unless $attr->has_trigger;
171 return defined($value)
172 ? sprintf('$attr->call_trigger(%s, %s);', $instance, $value)
173 : sprintf('$attr->call_trigger(%s);', $instance);
177 sub generate_accessor_method_inline {
178 Carp::cluck('The generate_accessor_method_inline method has been made private.'
179 . " The public version is deprecated and will be removed in a future release.\n");
180 shift->_generate_accessor_method_inline;
183 sub _generate_accessor_method_inline {
185 my $attr = $self->associated_attribute;
186 my $attr_name = $attr->name;
187 my $meta_instance = $attr->associated_class->instance_metaclass;
189 my ( $code, $e ) = $self->_eval_closure(
192 . 'if(scalar(@_) == 2){'
193 . 'my $value = ' . $meta_instance->inline_set_slot_value('$_[0]', $attr_name, '$_[1]') . ';'
194 . $self->_inline_call_trigger($attr, '$_[0]', '$value')
196 . $meta_instance->inline_get_slot_value('$_[0]', $attr_name)
199 confess "Could not generate inline accessor because : $e" if $e;
204 sub generate_reader_method_inline {
205 Carp::cluck('The generate_reader_method_inline method has been made private.'
206 . " The public version is deprecated and will be removed in a future release.\n");
207 shift->_generate_reader_method_inline;
210 sub _generate_reader_method_inline {
212 my $attr = $self->associated_attribute;
213 my $attr_name = $attr->name;
214 my $meta_instance = $attr->associated_class->instance_metaclass;
216 my ( $code, $e ) = $self->_eval_closure(
219 . 'confess "Cannot assign a value to a read-only accessor" if @_ > 1;'
220 . $meta_instance->inline_get_slot_value('$_[0]', $attr_name)
223 confess "Could not generate inline reader because : $e" if $e;
228 sub generate_writer_method_inline {
229 Carp::cluck('The generate_writer_method_inline method has been made private.'
230 . " The public version is deprecated and will be removed in a future release.\n");
231 shift->_generate_writer_method_inline;
234 sub _generate_writer_method_inline {
236 my $attr = $self->associated_attribute;
237 my $attr_name = $attr->name;
238 my $meta_instance = $attr->associated_class->instance_metaclass;
240 my ( $code, $e ) = $self->_eval_closure(
243 . 'my $value = ' . $meta_instance->inline_set_slot_value('$_[0]', $attr_name, '$_[1]') . ';'
244 . $self->_inline_call_trigger($attr, '$_[0]', '$value')
248 confess "Could not generate inline writer because : $e" if $e;
253 sub generate_predicate_method_inline {
254 Carp::cluck('The generate_predicate_method_inline method has been made private.'
255 . " The public version is deprecated and will be removed in a future release.\n");
256 shift->_generate_predicate_method_inline;
259 sub _generate_predicate_method_inline {
261 my $attr = $self->associated_attribute;
262 my $attr_name = $attr->name;
263 my $meta_instance = $attr->associated_class->instance_metaclass;
265 my ( $code, $e ) = $self->_eval_closure(
268 . $meta_instance->inline_is_slot_initialized('$_[0]', $attr_name)
271 confess "Could not generate inline predicate because : $e" if $e;
276 sub generate_clearer_method_inline {
277 Carp::cluck('The generate_clearer_method_inline method has been made private.'
278 . " The public version is deprecated and will be removed in a future release.\n");
279 shift->_generate_clearer_method_inline;
282 sub _generate_clearer_method_inline {
284 my $attr = $self->associated_attribute;
285 my $attr_name = $attr->name;
286 my $meta_instance = $attr->associated_class->instance_metaclass;
288 my ( $code, $e ) = $self->_eval_closure(
291 . $meta_instance->inline_deinitialize_slot('$_[0]', $attr_name) . ';'
292 . $self->_inline_call_trigger($attr, '$_[0]')
296 confess "Could not generate inline clearer because : $e" if $e;
309 Class::MOP::Method::Accessor - Method Meta Object for accessors
313 use Class::MOP::Method::Accessor;
315 my $reader = Class::MOP::Method::Accessor->new(
316 attribute => $attribute,
318 accessor_type => 'reader',
321 $reader->body->execute($instance); # call the reader method
325 This is a subclass of <Class::MOP::Method> which is used by
326 C<Class::MOP::Attribute> to generate accessor code. It handles
327 generation of readers, writers, predicates and clearers. For each type
328 of method, it can either create a subroutine reference, or actually
329 inline code by generating a string and C<eval>'ing it.
335 =item B<< Class::MOP::Method::Accessor->new(%options) >>
337 This returns a new C<Class::MOP::Method::Accessor> based on the
338 C<%options> provided.
344 This is the C<Class::MOP::Attribute> for which accessors are being
345 generated. This option is required.
347 =item * accessor_type
349 This is a string which should be one of "reader", "writer",
350 "accessor", "predicate", or "clearer". This is the type of method
351 being generated. This option is required.
355 This indicates whether or not the accessor should be inlined. This
360 The method name (without a package name). This is required.
364 The package name for the method. This is required.
368 =item B<< $metamethod->accessor_type >>
370 Returns the accessor type which was passed to C<new>.
372 =item B<< $metamethod->is_inline >>
374 Returns a boolean indicating whether or not the accessor is inlined.
376 =item B<< $metamethod->associated_attribute >>
378 This returns the L<Class::MOP::Attribute> object which was passed to
381 =item B<< $metamethod->body >>
383 The method itself is I<generated> when the accessor object is
390 Stevan Little E<lt>stevan@iinteractive.comE<gt>
392 =head1 COPYRIGHT AND LICENSE
394 Copyright 2006-2009 by Infinity Interactive, Inc.
396 L<http://www.iinteractive.com>
398 This library is free software; you can redistribute it and/or modify
399 it under the same terms as Perl itself.