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