2 package Class::MOP::Method::Accessor;
8 use Scalar::Util 'blessed', 'weaken';
10 our $VERSION = '0.94';
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'});
45 return Class::MOP::Class->initialize($class)->new_object(@_)
46 if $class ne __PACKAGE__;
48 my $params = @_ == 1 ? $_[0] : {@_};
51 # inherited from Class::MOP::Method
52 body => $params->{body},
53 associated_metaclass => $params->{associated_metaclass},
54 package_name => $params->{package_name},
55 name => $params->{name},
56 original_method => $params->{original_method},
58 # inherit from Class::MOP::Generated
59 is_inline => $params->{is_inline} || 0,
60 definition_context => $params->{definition_context},
62 # defined in this class
63 attribute => $params->{attribute},
64 accessor_type => $params->{accessor_type},
70 sub associated_attribute { (shift)->{'attribute'} }
71 sub accessor_type { (shift)->{'accessor_type'} }
75 sub _initialize_body {
78 my $method_name = join "_" => (
82 ($self->is_inline ? 'inline' : ())
85 $self->{'body'} = $self->$method_name();
90 sub _generate_accessor_method {
91 my $attr = (shift)->associated_attribute;
93 $attr->set_value($_[0], $_[1]) if scalar(@_) == 2;
94 $attr->get_value($_[0]);
98 sub _generate_reader_method {
99 my $attr = (shift)->associated_attribute;
101 confess "Cannot assign a value to a read-only accessor" if @_ > 1;
102 $attr->get_value($_[0]);
107 sub _generate_writer_method {
108 my $attr = (shift)->associated_attribute;
110 $attr->set_value($_[0], $_[1]);
114 sub _generate_predicate_method {
115 my $attr = (shift)->associated_attribute;
117 $attr->has_value($_[0])
121 sub _generate_clearer_method {
122 my $attr = (shift)->associated_attribute;
124 $attr->clear_value($_[0])
130 sub _generate_accessor_method_inline {
132 my $attr = $self->associated_attribute;
133 my $attr_name = $attr->name;
134 my $meta_instance = $attr->associated_class->instance_metaclass;
136 my ( $code, $e ) = $self->_eval_closure(
139 . $meta_instance->inline_set_slot_value('$_[0]', $attr_name, '$_[1]')
140 . ' if scalar(@_) == 2; '
141 . $meta_instance->inline_get_slot_value('$_[0]', $attr_name)
144 confess "Could not generate inline accessor because : $e" if $e;
149 sub _generate_reader_method_inline {
151 my $attr = $self->associated_attribute;
152 my $attr_name = $attr->name;
153 my $meta_instance = $attr->associated_class->instance_metaclass;
155 my ( $code, $e ) = $self->_eval_closure(
158 . 'confess "Cannot assign a value to a read-only accessor" if @_ > 1;'
159 . $meta_instance->inline_get_slot_value('$_[0]', $attr_name)
162 confess "Could not generate inline reader because : $e" if $e;
167 sub _generate_writer_method_inline {
169 my $attr = $self->associated_attribute;
170 my $attr_name = $attr->name;
171 my $meta_instance = $attr->associated_class->instance_metaclass;
173 my ( $code, $e ) = $self->_eval_closure(
176 . $meta_instance->inline_set_slot_value('$_[0]', $attr_name, '$_[1]')
179 confess "Could not generate inline writer because : $e" if $e;
184 sub _generate_predicate_method_inline {
186 my $attr = $self->associated_attribute;
187 my $attr_name = $attr->name;
188 my $meta_instance = $attr->associated_class->instance_metaclass;
190 my ( $code, $e ) = $self->_eval_closure(
193 . $meta_instance->inline_is_slot_initialized('$_[0]', $attr_name)
196 confess "Could not generate inline predicate because : $e" if $e;
201 sub _generate_clearer_method_inline {
203 my $attr = $self->associated_attribute;
204 my $attr_name = $attr->name;
205 my $meta_instance = $attr->associated_class->instance_metaclass;
207 my ( $code, $e ) = $self->_eval_closure(
210 . $meta_instance->inline_deinitialize_slot('$_[0]', $attr_name)
213 confess "Could not generate inline clearer because : $e" if $e;
226 Class::MOP::Method::Accessor - Method Meta Object for accessors
230 use Class::MOP::Method::Accessor;
232 my $reader = Class::MOP::Method::Accessor->new(
233 attribute => $attribute,
235 accessor_type => 'reader',
238 $reader->body->execute($instance); # call the reader method
242 This is a subclass of <Class::MOP::Method> which is used by
243 C<Class::MOP::Attribute> to generate accessor code. It handles
244 generation of readers, writers, predicates and clearers. For each type
245 of method, it can either create a subroutine reference, or actually
246 inline code by generating a string and C<eval>'ing it.
252 =item B<< Class::MOP::Method::Accessor->new(%options) >>
254 This returns a new C<Class::MOP::Method::Accessor> based on the
255 C<%options> provided.
261 This is the C<Class::MOP::Attribute> for which accessors are being
262 generated. This option is required.
264 =item * accessor_type
266 This is a string which should be one of "reader", "writer",
267 "accessor", "predicate", or "clearer". This is the type of method
268 being generated. This option is required.
272 This indicates whether or not the accessor should be inlined. This
277 The method name (without a package name). This is required.
281 The package name for the method. This is required.
285 =item B<< $metamethod->accessor_type >>
287 Returns the accessor type which was passed to C<new>.
289 =item B<< $metamethod->is_inline >>
291 Returns a boolean indicating whether or not the accessor is inlined.
293 =item B<< $metamethod->associated_attribute >>
295 This returns the L<Class::MOP::Attribute> object which was passed to
298 =item B<< $metamethod->body >>
300 The method itself is I<generated> when the accessor object is
307 Stevan Little E<lt>stevan@iinteractive.comE<gt>
309 =head1 COPYRIGHT AND LICENSE
311 Copyright 2006-2009 by Infinity Interactive, Inc.
313 L<http://www.iinteractive.com>
315 This library is free software; you can redistribute it and/or modify
316 it under the same terms as Perl itself.