2 package Class::MOP::Method::Accessor;
8 use Scalar::Util 'blessed', 'weaken';
10 our $VERSION = '0.92';
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'});
38 weaken($self->{'associated_metaclass'});
40 $self->_initialize_body;
48 return Class::MOP::Class->initialize($class)->new_object(@_)
49 if $class ne __PACKAGE__;
51 my $params = @_ == 1 ? $_[0] : {@_};
54 # inherited from Class::MOP::Method
55 body => $params->{body},
56 associated_metaclass => $params->{associated_metaclass},
57 package_name => $params->{package_name},
58 name => $params->{name},
59 original_method => $params->{original_method},
61 # inherit from Class::MOP::Generated
62 is_inline => $params->{is_inline},
63 definition_context => $params->{definition_context},
65 # defined in this class
66 attribute => $params->{attribute},
67 accessor_type => $params->{accessor_type},
74 sub _initialize_body {
77 my $method_name = join "_" => (
83 $self->{'body'} = $self->$method_name();
89 sub _generate_accessor_method {
92 if(my $xs = $self->associated_metaclass->instance_metaclass->can_xs()){
93 return $self->_generate_accessor_method_xs($xs);
97 return $self->_generate_accessor_method_inline();
100 return $self->_generate_accessor_method_basic();
101 <<<<<<< HEAD:lib/Class/MOP/Method/Accessor.pm
104 sub _generate_reader_method {
107 if(my $xs = $self->associated_metaclass->instance_metaclass->can_xs()){
108 return $self->_generate_reader_method_xs($xs);
111 if($self->is_inline){
112 return $self->_generate_reader_method_inline();
115 return $self->_generate_reader_method_basic();
118 sub _generate_writer_method {
121 if(my $xs = $self->associated_metaclass->instance_metaclass->can_xs()){
122 return $self->_generate_writer_method_xs($xs);
125 if($self->is_inline){
126 return $self->_generate_writer_method_inline();
129 return $self->_generate_writer_method_basic();
132 sub _generate_clearer_method {
135 if(my $xs = $self->associated_metaclass->instance_metaclass->can_xs()){
136 return $self->_generate_clearer_method_xs($xs);
139 if($self->is_inline){
140 return $self->_generate_clearer_method_inline();
143 return $self->_generate_clearer_method_basic();
146 sub _generate_predicate_method {
149 if(my $xs = $self->associated_metaclass->instance_metaclass->can_xs()){
150 return $self->_generate_predicate_method_xs($xs);
153 if($self->is_inline){
154 return $self->_generate_predicate_method_inline();
157 return $self->_generate_predicate_method_basic();
166 sub _generate_reader_method {
169 if(my $xs = $self->associated_metaclass->instance_metaclass->can_xs()){
170 return $self->_generate_reader_method_xs($xs);
173 if($self->is_inline){
174 return $self->_generate_reader_method_inline();
177 return $self->_generate_reader_method_basic();
180 sub _generate_writer_method {
183 if(my $xs = $self->associated_metaclass->instance_metaclass->can_xs()){
184 return $self->_generate_writer_method_xs($xs);
187 if($self->is_inline){
188 return $self->_generate_writer_method_inline();
191 return $self->_generate_writer_method_basic();
194 sub _generate_clearer_method {
197 if(my $xs = $self->associated_metaclass->instance_metaclass->can_xs()){
198 return $self->_generate_clearer_method_xs($xs);
201 if($self->is_inline){
202 return $self->_generate_clearer_method_inline();
205 return $self->_generate_clearer_method_basic();
208 sub _generate_predicate_method {
211 if(my $xs = $self->associated_metaclass->instance_metaclass->can_xs()){
212 return $self->_generate_predicate_method_xs($xs);
215 if($self->is_inline){
216 return $self->_generate_predicate_method_inline();
219 return $self->_generate_predicate_method_basic();
225 sub _generate_accessor_method_basic {
226 my $attr = (shift)->associated_attribute;
228 $attr->set_value($_[0], $_[1]) if scalar(@_) == 2;
229 $attr->get_value($_[0]);
233 sub _generate_reader_method_basic {
234 my $attr = (shift)->associated_attribute;
236 confess "Cannot assign a value to a read-only accessor" if @_ > 1;
237 $attr->get_value($_[0]);
241 sub _generate_writer_method_basic {
242 my $attr = (shift)->associated_attribute;
244 $attr->set_value($_[0], $_[1]);
248 sub _generate_predicate_method_basic {
249 my $attr = (shift)->associated_attribute;
251 $attr->has_value($_[0])
255 sub _generate_clearer_method_basic {
256 my $attr = (shift)->associated_attribute;
258 $attr->clear_value($_[0])
264 sub _generate_accessor_method_inline {
266 my $attr = $self->associated_attribute;
267 my $attr_name = $attr->name;
268 my $meta_instance = $attr->associated_class->instance_metaclass;
270 my ( $code, $e ) = $self->_eval_closure(
273 . $meta_instance->inline_set_slot_value('$_[0]', $attr_name, '$_[1]')
274 . ' if scalar(@_) == 2; '
275 . $meta_instance->inline_get_slot_value('$_[0]', $attr_name)
278 confess "Could not generate inline accessor because : $e" if $e;
283 sub _generate_reader_method_inline {
285 my $attr = $self->associated_attribute;
286 my $attr_name = $attr->name;
287 my $meta_instance = $attr->associated_class->instance_metaclass;
289 my ( $code, $e ) = $self->_eval_closure(
292 . 'confess "Cannot assign a value to a read-only accessor" if @_ > 1;'
293 . $meta_instance->inline_get_slot_value('$_[0]', $attr_name)
296 confess "Could not generate inline reader because : $e" if $e;
301 sub _generate_writer_method_inline {
303 my $attr = $self->associated_attribute;
304 my $attr_name = $attr->name;
305 my $meta_instance = $attr->associated_class->instance_metaclass;
307 my ( $code, $e ) = $self->_eval_closure(
310 . $meta_instance->inline_set_slot_value('$_[0]', $attr_name, '$_[1]')
313 confess "Could not generate inline writer because : $e" if $e;
318 sub _generate_predicate_method_inline {
320 my $attr = $self->associated_attribute;
321 my $attr_name = $attr->name;
322 my $meta_instance = $attr->associated_class->instance_metaclass;
324 my ( $code, $e ) = $self->_eval_closure(
327 . $meta_instance->inline_is_slot_initialized('$_[0]', $attr_name)
330 confess "Could not generate inline predicate because : $e" if $e;
335 sub _generate_clearer_method_inline {
337 my $attr = $self->associated_attribute;
338 my $attr_name = $attr->name;
339 my $meta_instance = $attr->associated_class->instance_metaclass;
341 my ( $code, $e ) = $self->_eval_closure(
344 . $meta_instance->inline_deinitialize_slot('$_[0]', $attr_name)
347 confess "Could not generate inline clearer because : $e" if $e;
360 Class::MOP::Method::Accessor - Method Meta Object for accessors
364 use Class::MOP::Method::Accessor;
366 my $reader = Class::MOP::Method::Accessor->new(
367 attribute => $attribute,
369 accessor_type => 'reader',
372 $reader->body->execute($instance); # call the reader method
376 This is a subclass of <Class::MOP::Method> which is used by
377 C<Class::MOP::Attribute> to generate accessor code. It handles
378 generation of readers, writers, predicates and clearers. For each type
379 of method, it can either create a subroutine reference, or actually
380 inline code by generating a string and C<eval>'ing it.
386 =item B<< Class::MOP::Method::Accessor->new(%options) >>
388 This returns a new C<Class::MOP::Method::Accessor> based on the
389 C<%options> provided.
395 This is the C<Class::MOP::Attribute> for which accessors are being
396 generated. This option is required.
398 =item * accessor_type
400 This is a string which should be one of "reader", "writer",
401 "accessor", "predicate", or "clearer". This is the type of method
402 being generated. This option is required.
406 This indicates whether or not the accessor should be inlined. This
411 The method name (without a package name). This is required.
415 The package name for the method. This is required.
419 =item B<< $metamethod->accessor_type >>
421 Returns the accessor type which was passed to C<new>.
423 =item B<< $metamethod->is_inline >>
425 Returns a boolean indicating whether or not the accessor is inlined.
427 =item B<< $metamethod->associated_attribute >>
429 This returns the L<Class::MOP::Attribute> object which was passed to
432 =item B<< $metamethod->body >>
434 The method itself is I<generated> when the accessor object is
441 Stevan Little E<lt>stevan@iinteractive.comE<gt>
443 =head1 COPYRIGHT AND LICENSE
445 Copyright 2006-2009 by Infinity Interactive, Inc.
447 L<http://www.iinteractive.com>
449 This library is free software; you can redistribute it and/or modify
450 it under the same terms as Perl itself.