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