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