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