fixed
[gitmo/Class-MOP.git] / lib / Class / MOP / Attribute.pm
CommitLineData
8b978dd5 1
2package Class::MOP::Attribute;
3
4use strict;
5use warnings;
6
ba38bf08 7use Class::MOP::Method::Accessor;
8
2eb717d5 9use Carp 'confess';
9ec169fe 10use Scalar::Util 'blessed', 'reftype', 'weaken';
2eb717d5 11
742fb371 12our $VERSION = '0.19';
f0480c45 13our $AUTHORITY = 'cpan:STEVAN';
8b978dd5 14
b1897d4d 15use base 'Class::MOP::Object';
16
1d68af04 17sub meta {
727919c5 18 require Class::MOP::Class;
aa448b16 19 Class::MOP::Class->initialize(blessed($_[0]) || $_[0]);
727919c5 20}
2eb717d5 21
727919c5 22# NOTE: (meta-circularity)
1d68af04 23# This method will be replaced in the
24# boostrap section of Class::MOP, by
25# a new version which uses the
727919c5 26# &Class::MOP::Class::construct_instance
27# method to build an attribute meta-object
28# which itself is described with attribute
1d68af04 29# meta-objects.
727919c5 30# - Ain't meta-circularity grand? :)
8b978dd5 31sub new {
32 my $class = shift;
33 my $name = shift;
1d68af04 34 my %options = @_;
35
cbd9f942 36 (defined $name && $name)
8b978dd5 37 || confess "You must provide a name for the attribute";
1d68af04 38
39 $options{init_arg} = $name
5659d76e 40 if not exists $options{init_arg};
1d68af04 41 if(exists $options{builder}){
42 confess("builder must be a defined scalar value which is a method name")
43 if ref $options{builder} || !(defined $options{builder});
44 confess("Setting both default and builder is not allowed.")
45 if exists $options{default};
8fe581e5 46 } else {
47 (is_default_a_coderef(\%options))
48 || confess("References are not allowed as default values, you must ".
49 "wrap then in a CODE reference (ex: sub { [] } and not [])")
50 if exists $options{default} && ref $options{default};
1d68af04 51 }
8b978dd5 52 bless {
c23184fc 53 '$!name' => $name,
54 '$!accessor' => $options{accessor},
55 '$!reader' => $options{reader},
56 '$!writer' => $options{writer},
57 '$!predicate' => $options{predicate},
58 '$!clearer' => $options{clearer},
1d68af04 59 '$!builder' => $options{builder},
c23184fc 60 '$!init_arg' => $options{init_arg},
61 '$!default' => $options{default},
1d68af04 62 # keep a weakened link to the
9ec169fe 63 # class we are associated with
c23184fc 64 '$!associated_class' => undef,
1d68af04 65 # and a list of the methods
3545c727 66 # associated with this attr
c23184fc 67 '@!associated_methods' => [],
8b978dd5 68 } => $class;
69}
70
7b31baf4 71# NOTE:
1d68af04 72# this is a primative (and kludgy) clone operation
16e960bd 73# for now, it will be replaced in the Class::MOP
1d68af04 74# bootstrap with a proper one, however we know
5659d76e 75# that this one will work fine for now.
76sub clone {
77 my $self = shift;
78 my %options = @_;
79 (blessed($self))
80 || confess "Can only clone an instance";
81 return bless { %{$self}, %options } => blessed($self);
82}
83
bd4e03f9 84sub initialize_instance_slot {
f892c0f0 85 my ($self, $meta_instance, $instance, $params) = @_;
c23184fc 86 my $init_arg = $self->{'$!init_arg'};
bd4e03f9 87 # try to fetch the init arg from the %params ...
8d2d4c67 88
1d68af04 89 # if nothing was in the %params, we can use the
bd4e03f9 90 # attribute's default value (if it has one)
8d2d4c67 91 if(exists $params->{$init_arg}){
92 $meta_instance->set_slot_value($instance, $self->name, $params->{$init_arg});
b7bdffc3 93 }
94 elsif (defined $self->{'$!default'}) {
8d2d4c67 95 $meta_instance->set_slot_value($instance, $self->name, $self->default($instance));
b7bdffc3 96 }
97 elsif (defined( my $builder = $self->{'$!builder'})) {
98 if ($builder = $instance->can($builder)) {
8d2d4c67 99 $meta_instance->set_slot_value($instance, $self->name, $instance->$builder);
b7bdffc3 100 }
101 else {
232c4e13 102 confess(blessed($instance)." does not support builder method '". $self->{'$!builder'} ."' for attribute '" . $self->name . "'");
8fe581e5 103 }
1d68af04 104 }
bd4e03f9 105}
106
5659d76e 107# NOTE:
1d68af04 108# the next bunch of methods will get bootstrapped
7b31baf4 109# away in the Class::MOP bootstrapping section
110
c23184fc 111sub name { $_[0]->{'$!name'} }
c50c603e 112
c23184fc 113sub associated_class { $_[0]->{'$!associated_class'} }
114sub associated_methods { $_[0]->{'@!associated_methods'} }
7b31baf4 115
c23184fc 116sub has_accessor { defined($_[0]->{'$!accessor'}) ? 1 : 0 }
117sub has_reader { defined($_[0]->{'$!reader'}) ? 1 : 0 }
118sub has_writer { defined($_[0]->{'$!writer'}) ? 1 : 0 }
119sub has_predicate { defined($_[0]->{'$!predicate'}) ? 1 : 0 }
120sub has_clearer { defined($_[0]->{'$!clearer'}) ? 1 : 0 }
1d68af04 121sub has_builder { defined($_[0]->{'$!builder'}) ? 1 : 0 }
c23184fc 122sub has_init_arg { defined($_[0]->{'$!init_arg'}) ? 1 : 0 }
123sub has_default { defined($_[0]->{'$!default'}) ? 1 : 0 }
c50c603e 124
1d68af04 125sub accessor { $_[0]->{'$!accessor'} }
c23184fc 126sub reader { $_[0]->{'$!reader'} }
127sub writer { $_[0]->{'$!writer'} }
128sub predicate { $_[0]->{'$!predicate'} }
129sub clearer { $_[0]->{'$!clearer'} }
1d68af04 130sub builder { $_[0]->{'$!builder'} }
c23184fc 131sub init_arg { $_[0]->{'$!init_arg'} }
c50c603e 132
7b31baf4 133# end bootstrapped away method section.
134# (all methods below here are kept intact)
135
b25109b1 136sub get_read_method { $_[0]->reader || $_[0]->accessor }
137sub get_write_method { $_[0]->writer || $_[0]->accessor }
138
5da16d1b 139sub get_read_method_ref {
140 my $self = shift;
742fb371 141 if ((my $reader = $self->get_read_method) && $self->associated_class) {
5da16d1b 142 return $self->associated_class->get_method($reader);
143 }
144 else {
145 return sub { $self->get_value(@_) };
146 }
147}
148
149sub get_write_method_ref {
150 my $self = shift;
742fb371 151 if ((my $writer = $self->get_write_method) && $self->associated_class) {
152 return $self->associated_class->get_method($writer);
5da16d1b 153 }
154 else {
155 return sub { $self->set_value(@_) };
156 }
157}
158
1d68af04 159sub is_default_a_coderef {
160 ('CODE' eq (reftype($_[0]->{'$!default'} || $_[0]->{default}) || ''))
c0cbf4d9 161}
162
1d68af04 163sub default {
c0cbf4d9 164 my ($self, $instance) = @_;
9363ea89 165 if (defined $instance && $self->is_default_a_coderef) {
1d68af04 166 # if the default is a CODE ref, then
727919c5 167 # we pass in the instance and default
1d68af04 168 # can return a value based on that
727919c5 169 # instance. Somewhat crude, but works.
c23184fc 170 return $self->{'$!default'}->($instance);
1d68af04 171 }
c23184fc 172 $self->{'$!default'};
c50c603e 173}
8b978dd5 174
c57c8b10 175# slots
176
177sub slots { (shift)->name }
178
1d68af04 179# class association
727919c5 180
9ec169fe 181sub attach_to_class {
182 my ($self, $class) = @_;
183 (blessed($class) && $class->isa('Class::MOP::Class'))
184 || confess "You must pass a Class::MOP::Class instance (or a subclass)";
1d68af04 185 weaken($self->{'$!associated_class'} = $class);
9ec169fe 186}
187
188sub detach_from_class {
189 my $self = shift;
1d68af04 190 $self->{'$!associated_class'} = undef;
9ec169fe 191}
192
1d68af04 193# method association
3545c727 194
195sub associate_method {
196 my ($self, $method) = @_;
c23184fc 197 push @{$self->{'@!associated_methods'}} => $method;
3545c727 198}
199
16e960bd 200## Slot management
201
202sub set_value {
1396f86b 203 my ($self, $instance, $value) = @_;
16e960bd 204
3545c727 205 Class::MOP::Class->initialize(blessed($instance))
16e960bd 206 ->get_meta_instance
3545c727 207 ->set_slot_value($instance, $self->name, $value);
16e960bd 208}
209
210sub get_value {
1396f86b 211 my ($self, $instance) = @_;
16e960bd 212
3545c727 213 Class::MOP::Class->initialize(blessed($instance))
16e960bd 214 ->get_meta_instance
1396f86b 215 ->get_slot_value($instance, $self->name);
16e960bd 216}
217
3545c727 218sub has_value {
219 my ($self, $instance) = @_;
1d68af04 220
8d2d4c67 221 Class::MOP::Class->initialize(blessed($instance))
222 ->get_meta_instance
223 ->is_slot_initialized($instance, $self->name);
3545c727 224}
225
226sub clear_value {
227 my ($self, $instance) = @_;
1d68af04 228
3545c727 229 Class::MOP::Class->initialize(blessed($instance))
230 ->get_meta_instance
1d68af04 231 ->deinitialize_slot($instance, $self->name);
3545c727 232}
233
ba38bf08 234## load em up ...
c0cbf4d9 235
ba38bf08 236sub accessor_metaclass { 'Class::MOP::Method::Accessor' }
c0cbf4d9 237
9ec169fe 238sub process_accessors {
c0cbf4d9 239 my ($self, $type, $accessor, $generate_as_inline_methods) = @_;
013b1897 240 if (reftype($accessor)) {
241 (reftype($accessor) eq 'HASH')
7d28758b 242 || confess "bad accessor/reader/writer/predicate/clearer format, must be a HASH ref";
4d47b77f 243 my ($name, $method) = %{$accessor};
3545c727 244 $method = $self->accessor_metaclass->wrap($method);
245 $self->associate_method($method);
1d68af04 246 return ($name, $method);
2eb717d5 247 }
9ec169fe 248 else {
1d68af04 249 my $inline_me = ($generate_as_inline_methods && $self->associated_class->instance_metaclass->is_inlinable);
ba38bf08 250 my $method;
251 eval {
252 $method = $self->accessor_metaclass->new(
253 attribute => $self,
d90b42a6 254 is_inline => $inline_me,
ba38bf08 255 accessor_type => $type,
1d68af04 256 );
ba38bf08 257 };
1d68af04 258 confess "Could not create the '$type' method for " . $self->name . " because : $@" if $@;
3545c727 259 $self->associate_method($method);
ba38bf08 260 return ($accessor, $method);
1d68af04 261 }
9ec169fe 262}
263
264sub install_accessors {
c0cbf4d9 265 my $self = shift;
266 my $inline = shift;
267 my $class = $self->associated_class;
1d68af04 268
9ec169fe 269 $class->add_method(
c0cbf4d9 270 $self->process_accessors('accessor' => $self->accessor(), $inline)
9ec169fe 271 ) if $self->has_accessor();
272
1d68af04 273 $class->add_method(
c0cbf4d9 274 $self->process_accessors('reader' => $self->reader(), $inline)
9ec169fe 275 ) if $self->has_reader();
276
277 $class->add_method(
c0cbf4d9 278 $self->process_accessors('writer' => $self->writer(), $inline)
9ec169fe 279 ) if $self->has_writer();
280
281 $class->add_method(
c0cbf4d9 282 $self->process_accessors('predicate' => $self->predicate(), $inline)
9ec169fe 283 ) if $self->has_predicate();
1d68af04 284
7d28758b 285 $class->add_method(
286 $self->process_accessors('clearer' => $self->clearer(), $inline)
287 ) if $self->has_clearer();
1d68af04 288
9ec169fe 289 return;
2eb717d5 290}
291
b51af7f9 292{
293 my $_remove_accessor = sub {
294 my ($accessor, $class) = @_;
c50c603e 295 if (reftype($accessor) && reftype($accessor) eq 'HASH') {
296 ($accessor) = keys %{$accessor};
1d68af04 297 }
298 my $method = $class->get_method($accessor);
299 $class->remove_method($accessor)
ba38bf08 300 if (blessed($method) && $method->isa('Class::MOP::Method::Accessor'));
b51af7f9 301 };
1d68af04 302
b51af7f9 303 sub remove_accessors {
9ec169fe 304 my $self = shift;
2367814a 305 # TODO:
1d68af04 306 # we really need to make sure to remove from the
307 # associates methods here as well. But this is
308 # such a slimly used method, I am not worried
2367814a 309 # about it right now.
9ec169fe 310 $_remove_accessor->($self->accessor(), $self->associated_class()) if $self->has_accessor();
311 $_remove_accessor->($self->reader(), $self->associated_class()) if $self->has_reader();
312 $_remove_accessor->($self->writer(), $self->associated_class()) if $self->has_writer();
313 $_remove_accessor->($self->predicate(), $self->associated_class()) if $self->has_predicate();
7d28758b 314 $_remove_accessor->($self->clearer(), $self->associated_class()) if $self->has_clearer();
1d68af04 315 return;
b51af7f9 316 }
317
8b978dd5 318}
319
3201;
321
322__END__
323
324=pod
325
1d68af04 326=head1 NAME
8b978dd5 327
328Class::MOP::Attribute - Attribute Meta Object
329
330=head1 SYNOPSIS
1d68af04 331
8b978dd5 332 Class::MOP::Attribute->new('$foo' => (
fe122940 333 accessor => 'foo', # dual purpose get/set accessor
1d68af04 334 predicate => 'has_foo' # predicate check for defined-ness
fe122940 335 init_arg => '-foo', # class->new will look for a -foo key
336 default => 'BAR IS BAZ!' # if no -foo key is provided, use this
8b978dd5 337 ));
1d68af04 338
8b978dd5 339 Class::MOP::Attribute->new('$.bar' => (
fe122940 340 reader => 'bar', # getter
1d68af04 341 writer => 'set_bar', # setter
342 predicate => 'has_bar' # predicate check for defined-ness
fe122940 343 init_arg => ':bar', # class->new will look for a :bar key
8b978dd5 344 # no default value means it is undef
345 ));
346
347=head1 DESCRIPTION
348
fe122940 349The Attribute Protocol is almost entirely an invention of this module,
1d68af04 350and is completely optional to this MOP. This is because Perl 5 does not
351have consistent notion of what is an attribute of a class. There are
352so many ways in which this is done, and very few (if any) are
fe122940 353easily discoverable by this module.
552e3d24 354
1d68af04 355So, all that said, this module attempts to inject some order into this
356chaos, by introducing a consistent API which can be used to create
fe122940 357object attributes.
552e3d24 358
359=head1 METHODS
360
361=head2 Creation
362
363=over 4
364
fe122940 365=item B<new ($name, ?%options)>
366
1d68af04 367An attribute must (at the very least), have a C<$name>. All other
a2e85e6c 368C<%options> are contained added as key-value pairs. Acceptable keys
fe122940 369are as follows:
370
371=over 4
372
373=item I<init_arg>
374
1d68af04 375This should be a string value representing the expected key in
376an initialization hash. For instance, if we have an I<init_arg>
fe122940 377value of C<-foo>, then the following code will Just Work.
378
379 MyClass->meta->construct_instance(-foo => "Hello There");
380
1d68af04 381In an init_arg is not assigned, it will automatically use the
7b31baf4 382value of C<$name>.
383
fe122940 384=item I<default>
385
1d68af04 386The value of this key is the default value which
387C<Class::MOP::Class::construct_instance> will initialize the
388attribute to.
389
390=item I<builder>
391
392The value of this key is the name of the method that will be
393called to obtain the value used to initialize the attribute.
394This should be a method in the class associated with the attribute,
395not a method in the attribute class itself.
fe122940 396
397B<NOTE:>
1d68af04 398If the value is a simple scalar (string or number), then it can
399be just passed as is. However, if you wish to initialize it with
400a HASH or ARRAY ref, then you need to wrap that inside a CODE
fe122940 401reference, like so:
402
403 Class::MOP::Attribute->new('@foo' => (
404 default => sub { [] },
405 ));
1d68af04 406
407 # or ...
408
fe122940 409 Class::MOP::Attribute->new('%foo' => (
410 default => sub { {} },
1d68af04 411 ));
fe122940 412
1d68af04 413If you wish to initialize an attribute with a CODE reference
fe122940 414itself, then you need to wrap that in a subroutine as well, like
415so:
1d68af04 416
fe122940 417 Class::MOP::Attribute->new('&foo' => (
418 default => sub { sub { print "Hello World" } },
419 ));
420
1d68af04 421And lastly, if the value of your attribute is dependent upon
422some other aspect of the instance structure, then you can take
423advantage of the fact that when the I<default> value is a CODE
424reference, it is passed the raw (unblessed) instance structure
fe122940 425as it's only argument. So you can do things like this:
426
427 Class::MOP::Attribute->new('$object_identity' => (
428 default => sub { Scalar::Util::refaddr($_[0]) },
429 ));
430
1d68af04 431This last feature is fairly limited as there is no gurantee of
432the order of attribute initializations, so you cannot perform
433any kind of dependent initializations. However, if this is
434something you need, you could subclass B<Class::MOP::Class> and
435this class to acheive it. However, this is currently left as
fe122940 436an exercise to the reader :).
437
438=back
439
7d28758b 440The I<accessor>, I<reader>, I<writer>, I<predicate> and I<clearer> keys can
441contain either; the name of the method and an appropriate default one will be
442generated for you, B<or> a HASH ref containing exactly one key (which will be
443used as the name of the method) and one value, which should contain a CODE
444reference which will be installed as the method itself.
59e7697f 445
446=over 4
447
448=item I<accessor>
449
1d68af04 450The I<accessor> is a standard perl-style read/write accessor. It will
451return the value of the attribute, and if a value is passed as an argument,
fe122940 452it will assign that value to the attribute.
453
454B<NOTE:>
1d68af04 455This method will properly handle the following code, by assigning an
fe122940 456C<undef> value to the attribute.
457
458 $object->set_something(undef);
459
59e7697f 460=item I<reader>
461
1d68af04 462This is a basic read-only accessor, it will just return the value of
fe122940 463the attribute.
464
59e7697f 465=item I<writer>
466
1d68af04 467This is a basic write accessor, it accepts a single argument, and
468assigns that value to the attribute. This method does not intentially
469return a value, however perl will return the result of the last
470expression in the subroutine, which returns in this returning the
471same value that it was passed.
59e7697f 472
fe122940 473B<NOTE:>
1d68af04 474This method will properly handle the following code, by assigning an
fe122940 475C<undef> value to the attribute.
59e7697f 476
fe122940 477 $object->set_something();
478
479=item I<predicate>
480
1d68af04 481This is a basic test to see if the value of the attribute is not
482C<undef>. It will return true (C<1>) if the attribute's value is
fe122940 483defined, and false (C<0>) otherwise.
59e7697f 484
7d28758b 485=item I<clearer>
486
487This is the a method that will uninitialize the attr, reverting lazy values
488back to their "unfulfilled" state.
489
59e7697f 490=back
552e3d24 491
bd4e03f9 492=item B<clone (%options)>
493
494=item B<initialize_instance_slot ($instance, $params)>
495
1d68af04 496=back
552e3d24 497
16e960bd 498=head2 Value management
499
1d68af04 500These methods are basically "backdoors" to the instance, which can be used
501to bypass the regular accessors, but still stay within the context of the MOP.
2367814a 502
1d68af04 503These methods are not for general use, and should only be used if you really
2367814a 504know what you are doing.
505
16e960bd 506=over 4
507
3545c727 508=item B<set_value ($instance, $value)>
16e960bd 509
510Set the value without going through the accessor. Note that this may be done to
511even attributes with just read only accessors.
512
3545c727 513=item B<get_value ($instance)>
16e960bd 514
515Return the value without going through the accessor. Note that this may be done
516even to attributes with just write only accessors.
517
3545c727 518=item B<has_value ($instance)>
519
1d68af04 520Returns a boolean indicating if the item in the C<$instance> has a value in it.
2367814a 521This is basically what the default C<predicate> method calls.
522
3545c727 523=item B<clear_value ($instance)>
524
2367814a 525This will clear the value in the C<$instance>. This is basically what the default
1d68af04 526C<clearer> would call. Note that this may be done even if the attirbute does not
2367814a 527have any associated read, write or clear methods.
528
16e960bd 529=back
530
552e3d24 531=head2 Informational
532
1d68af04 533These are all basic read-only value accessors for the values
fe122940 534passed into C<new>. I think they are pretty much self-explanitory.
535
552e3d24 536=over 4
537
538=item B<name>
539
540=item B<accessor>
541
542=item B<reader>
543
544=item B<writer>
545
c50c603e 546=item B<predicate>
547
7d28758b 548=item B<clearer>
549
552e3d24 550=item B<init_arg>
551
495af518 552=item B<is_default_a_coderef>
553
fe122940 554=item B<default (?$instance)>
555
1d68af04 556As noted in the documentation for C<new> above, if the I<default>
fe122940 557value is a CODE reference, this accessor will pass a single additional
558argument C<$instance> into it and return the value.
552e3d24 559
c57c8b10 560=item B<slots>
561
1d68af04 562Returns a list of slots required by the attribute. This is usually
c57c8b10 563just one, which is the name of the attribute.
564
b25109b1 565=item B<get_read_method>
566
567=item B<get_write_method>
568
5da16d1b 569Return the name of a method name suitable for reading / writing the value
570of the attribute in the associated class. Suitable for use whether
571C<reader> and C<writer> or C<accessor> was used.
572
573=item B<get_read_method_ref>
574
575=item B<get_write_method_ref>
576
577Return the CODE reference of a method suitable for reading / writing the
578value of the attribute in the associated class. Suitable for use whether
579C<reader> and C<writer> or C<accessor> was specified or not.
580
581NOTE: If not reader/writer/accessor was specified, this will use the
582attribute get_value/set_value methods, which can be very inefficient.
b25109b1 583
552e3d24 584=back
585
586=head2 Informational predicates
587
a2e85e6c 588These are all basic predicate methods for the values passed into C<new>.
fe122940 589
552e3d24 590=over 4
591
592=item B<has_accessor>
593
552e3d24 594=item B<has_reader>
595
552e3d24 596=item B<has_writer>
597
c50c603e 598=item B<has_predicate>
599
7d28758b 600=item B<has_clearer>
601
552e3d24 602=item B<has_init_arg>
603
552e3d24 604=item B<has_default>
605
bf731086 606=item B<has_builder>
607
552e3d24 608=back
609
9ec169fe 610=head2 Class association
611
1d68af04 612These methods allow you to manage the attributes association with
613the class that contains it. These methods should not be used
2367814a 614lightly, nor are they very magical, they are mostly used internally
615and by metaclass instances.
616
9ec169fe 617=over 4
618
619=item B<associated_class>
620
2367814a 621This returns the metaclass this attribute is associated with.
622
9ec169fe 623=item B<attach_to_class ($class)>
624
1d68af04 625This will store a weaken reference to C<$class> internally. You should
2367814a 626note that just changing the class assocation will not remove the attribute
627from it's old class, and initialize it (and it's accessors) in the new
628C<$class>. It is up to you to do this manually.
629
9ec169fe 630=item B<detach_from_class>
631
1d68af04 632This will remove the weakened reference to the class. It does B<not>
633remove the attribute itself from the class (or remove it's accessors),
634you must do that yourself if you want too. Actually if that is what
635you want to do, you should probably be looking at
2367814a 636L<Class::MOP::Class::remove_attribute> instead.
637
9ec169fe 638=back
639
552e3d24 640=head2 Attribute Accessor generation
641
642=over 4
643
ba38bf08 644=item B<accessor_metaclass>
645
2367814a 646Accessors are generated by an accessor metaclass, which is usually
1d68af04 647a subclass of C<Class::MOP::Method::Accessor>. This method returns
2367814a 648the name of the accessor metaclass that this attribute uses.
649
650=item B<associate_method ($method)>
651
1d68af04 652This will associate a C<$method> with the given attribute which is
653used internally by the accessor generator.
3545c727 654
655=item B<associated_methods>
656
1d68af04 657This will return the list of methods which have been associated with
658the C<associate_method> methods.
2367814a 659
9ec169fe 660=item B<install_accessors>
2eb717d5 661
1d68af04 662This allows the attribute to generate and install code for it's own
663I<accessor/reader/writer/predicate> methods. This is called by
fe122940 664C<Class::MOP::Class::add_attribute>.
2eb717d5 665
1d68af04 666This method will call C<process_accessors> for each of the possible
9ec169fe 667method types (accessor, reader, writer & predicate).
668
669=item B<process_accessors ($type, $value)>
670
1d68af04 671This takes a C<$type> (accessor, reader, writer or predicate), and
9ec169fe 672a C<$value> (the value passed into the constructor for each of the
1d68af04 673different types). It will then either generate the method itself
674(using the C<generate_*_method> methods listed below) or it will
675use the custom method passed through the constructor.
9ec169fe 676
9ec169fe 677=item B<remove_accessors>
2eb717d5 678
1d68af04 679This allows the attribute to remove the method for it's own
680I<accessor/reader/writer/predicate/clearer>. This is called by
fe122940 681C<Class::MOP::Class::remove_attribute>.
2eb717d5 682
1d68af04 683NOTE: This does not currently remove methods from the list returned
2367814a 684by C<associated_methods>, that is on the TODO list.
685
2eb717d5 686=back
687
688=head2 Introspection
689
690=over 4
552e3d24 691
2eb717d5 692=item B<meta>
552e3d24 693
1d68af04 694This will return a B<Class::MOP::Class> instance which is related
fe122940 695to this class.
696
1d68af04 697It should also be noted that B<Class::MOP> will actually bootstrap
698this module by installing a number of attribute meta-objects into
699it's metaclass. This will allow this class to reap all the benifits
700of the MOP when subclassing it.
fe122940 701
552e3d24 702=back
703
1a09d9cc 704=head1 AUTHORS
8b978dd5 705
a2e85e6c 706Stevan Little E<lt>stevan@iinteractive.comE<gt>
8b978dd5 707
708=head1 COPYRIGHT AND LICENSE
709
2367814a 710Copyright 2006, 2007 by Infinity Interactive, Inc.
8b978dd5 711
712L<http://www.iinteractive.com>
713
714This library is free software; you can redistribute it and/or modify
1d68af04 715it under the same terms as Perl itself.
8b978dd5 716
16e960bd 717=cut
718
7d28758b 719