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