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