- refactoring attributes
[gitmo/Class-MOP.git] / lib / Class / MOP / Class.pm
1
2 package Class::MOP::Class;
3
4 use strict;
5 use warnings;
6
7 use Carp         'confess';
8 use Scalar::Util 'blessed', 'reftype';
9 use Sub::Name    'subname';
10 use B            'svref_2object';
11
12 our $VERSION = '0.01';
13
14 # Self-introspection
15
16 sub meta { $_[0]->initialize($_[0]) }
17
18 # Creation
19
20 {
21     # Metaclasses are singletons, so we cache them here.
22     # there is no need to worry about destruction though
23     # because they should die only when the program dies.
24     # After all, do package definitions even get reaped?
25     my %METAS;
26     sub initialize {
27         my ($class, $package_name) = @_;
28         (defined $package_name && $package_name)
29             || confess "You must pass a package name";        
30         return $METAS{$package_name} if exists $METAS{$package_name};
31         $METAS{$package_name} = $class->construct_class_instance($package_name);
32     }
33     
34     # NOTE: (meta-circularity) 
35     # this is a special form of &construct_instance 
36     # (see below), which is used to construct class
37     # meta-object instances for any Class::MOP::* 
38     # class. All other classes will use the more 
39     # normal &construct_instance.
40     sub construct_class_instance {
41         my ($class, $package_name) = @_;
42         (defined $package_name && $package_name)
43             || confess "You must pass a package name";    
44         $class = blessed($class) || $class;
45         if ($class =~ /^Class::MOP::/) {    
46             bless { 
47                 '$:pkg'   => $package_name, 
48                 '%:attrs' => {} 
49             } => $class;
50         }
51         else {
52             bless $class->meta->construct_instance(':pkg' => $package_name) => $class
53         }
54     }
55 }
56
57 sub create {
58     my ($class, $package_name, $package_version, %options) = @_;
59     (defined $package_name && $package_name)
60         || confess "You must pass a package name";
61     my $code = "package $package_name;";
62     $code .= "\$$package_name\:\:VERSION = '$package_version';" 
63         if defined $package_version;
64     eval $code;
65     confess "creation of $package_name failed : $@" if $@;    
66     my $meta = $class->initialize($package_name);
67     $meta->superclasses(@{$options{superclasses}})
68         if exists $options{superclasses};
69     # NOTE:
70     # process attributes first, so that they can 
71     # install accessors, but locally defined methods
72     # can then overwrite them. It is maybe a little odd, but
73     # I think this should be the order of things.
74     if (exists $options{attributes}) {
75         foreach my $attr (@{$options{attributes}}) {
76             $meta->add_attribute($attr);
77         }
78     }        
79     if (exists $options{methods}) {
80         foreach my $method_name (keys %{$options{methods}}) {
81             $meta->add_method($method_name, $options{methods}->{$method_name});
82         }
83     }  
84     return $meta;
85 }
86
87 # Instance Construction
88
89 sub construct_instance {
90     my ($class, %params) = @_;
91     my $instance = {};
92     foreach my $attr (map { $_->{attribute} } $class->compute_all_applicable_attributes()) {
93         # if the attr has an init_arg, use that, otherwise,
94         # use the attributes name itself as the init_arg
95         my $init_arg = $attr->has_init_arg() ? $attr->init_arg() : $attr->name;
96         # try to fetch the init arg from the %params ...
97         my $val;        
98         $val = $params{$init_arg} if exists $params{$init_arg};
99         # if nothing was in the %params, we can use the 
100         # attribute's default value (if it has one)
101         $val ||= $attr->default($instance) if $attr->has_default();
102         # now add this to the instance structure
103         $instance->{$attr->name} = $val;
104     }
105     return $instance;
106 }
107
108 # Informational 
109
110 sub name { $_[0]->{'$:pkg'} }
111
112 sub version {  
113     my $self = shift;
114     no strict 'refs';
115     ${$self->name . '::VERSION'};
116 }
117
118 # Inheritance
119
120 sub superclasses {
121     my $self = shift;
122     no strict 'refs';
123     if (@_) {
124         my @supers = @_;
125         @{$self->name . '::ISA'} = @supers;
126     }
127     @{$self->name . '::ISA'};        
128 }
129
130 sub class_precedence_list {
131     my $self = shift;
132     # NOTE:
133     # We need to check for ciruclar inheirtance here.
134     # This will do nothing if all is well, and blow
135     # up otherwise. Yes, it's an ugly hack, better 
136     # suggestions are welcome.
137     { $self->name->isa('This is a test for circular inheritance') }
138     # ... and no back to our regularly scheduled program
139     (
140         $self->name, 
141         map { 
142             $self->initialize($_)->class_precedence_list()
143         } $self->superclasses()
144     );   
145 }
146
147 ## Methods
148
149 sub add_method {
150     my ($self, $method_name, $method) = @_;
151     (defined $method_name && $method_name)
152         || confess "You must define a method name";
153     # use reftype here to allow for blessed subs ...
154     (reftype($method) && reftype($method) eq 'CODE')
155         || confess "Your code block must be a CODE reference";
156     my $full_method_name = ($self->name . '::' . $method_name);    
157         
158     no strict 'refs';
159     no warnings 'redefine';
160     *{$full_method_name} = subname $full_method_name => $method;
161 }
162
163 {
164
165     ## private utility functions for has_method
166     my $_find_subroutine_package_name = sub { eval { svref_2object($_[0])->GV->STASH->NAME } || '' };
167     my $_find_subroutine_name         = sub { eval { svref_2object($_[0])->GV->NAME        } || '' };
168
169     sub has_method {
170         my ($self, $method_name) = @_;
171         (defined $method_name && $method_name)
172             || confess "You must define a method name";    
173     
174         my $sub_name = ($self->name . '::' . $method_name);    
175         
176         no strict 'refs';
177         return 0 if !defined(&{$sub_name});        
178         return 0 if $_find_subroutine_package_name->(\&{$sub_name}) ne $self->name &&
179                     $_find_subroutine_name->(\&{$sub_name})         ne '__ANON__';
180         return 1;
181     }
182
183 }
184
185 sub get_method {
186     my ($self, $method_name) = @_;
187     (defined $method_name && $method_name)
188         || confess "You must define a method name";
189
190     no strict 'refs';    
191     return \&{$self->name . '::' . $method_name} 
192         if $self->has_method($method_name);   
193     return; # <- make sure to return undef
194 }
195
196 sub remove_method {
197     my ($self, $method_name) = @_;
198     (defined $method_name && $method_name)
199         || confess "You must define a method name";
200     
201     my $removed_method = $self->get_method($method_name);    
202     
203     no strict 'refs';
204     delete ${$self->name . '::'}{$method_name}
205         if defined $removed_method;
206         
207     return $removed_method;
208 }
209
210 sub get_method_list {
211     my $self = shift;
212     no strict 'refs';
213     grep { $self->has_method($_) } %{$self->name . '::'};
214 }
215
216 sub compute_all_applicable_methods {
217     my $self = shift;
218     my @methods;
219     # keep a record of what we have seen
220     # here, this will handle all the 
221     # inheritence issues because we are 
222     # using the &class_precedence_list
223     my (%seen_class, %seen_method);
224     foreach my $class ($self->class_precedence_list()) {
225         next if $seen_class{$class};
226         $seen_class{$class}++;
227         # fetch the meta-class ...
228         my $meta = $self->initialize($class);
229         foreach my $method_name ($meta->get_method_list()) { 
230             next if exists $seen_method{$method_name};
231             $seen_method{$method_name}++;
232             push @methods => {
233                 name  => $method_name, 
234                 class => $class,
235                 code  => $meta->get_method($method_name)
236             };
237         }
238     }
239     return @methods;
240 }
241
242 sub find_all_methods_by_name {
243     my ($self, $method_name) = @_;
244     (defined $method_name && $method_name)
245         || confess "You must define a method name to find";    
246     my @methods;
247     # keep a record of what we have seen
248     # here, this will handle all the 
249     # inheritence issues because we are 
250     # using the &class_precedence_list
251     my %seen_class;
252     foreach my $class ($self->class_precedence_list()) {
253         next if $seen_class{$class};
254         $seen_class{$class}++;
255         # fetch the meta-class ...
256         my $meta = $self->initialize($class);
257         push @methods => {
258             name  => $method_name, 
259             class => $class,
260             code  => $meta->get_method($method_name)
261         } if $meta->has_method($method_name);
262     }
263     return @methods;
264
265 }
266
267 ## Attributes
268
269 sub add_attribute {
270     my ($self,$attribute) = @_;
271     (blessed($attribute) && $attribute->isa('Class::MOP::Attribute'))
272         || confess "Your attribute must be an instance of Class::MOP::Attribute (or a subclass)";
273     $attribute->attach_to_class($self);
274     $attribute->install_accessors();        
275     $self->{'%:attrs'}->{$attribute->name} = $attribute;
276 }
277
278 sub has_attribute {
279     my ($self, $attribute_name) = @_;
280     (defined $attribute_name && $attribute_name)
281         || confess "You must define an attribute name";
282     exists $self->{'%:attrs'}->{$attribute_name} ? 1 : 0;    
283
284
285 sub get_attribute {
286     my ($self, $attribute_name) = @_;
287     (defined $attribute_name && $attribute_name)
288         || confess "You must define an attribute name";
289     return $self->{'%:attrs'}->{$attribute_name} 
290         if $self->has_attribute($attribute_name);    
291
292
293 sub remove_attribute {
294     my ($self, $attribute_name) = @_;
295     (defined $attribute_name && $attribute_name)
296         || confess "You must define an attribute name";
297     my $removed_attribute = $self->{'%:attrs'}->{$attribute_name};    
298     delete $self->{'%:attrs'}->{$attribute_name} 
299         if defined $removed_attribute;        
300     $removed_attribute->remove_accessors();        
301     $removed_attribute->detach_from_class();    
302     return $removed_attribute;
303
304
305 sub get_attribute_list {
306     my $self = shift;
307     keys %{$self->{'%:attrs'}};
308
309
310 sub compute_all_applicable_attributes {
311     my $self = shift;
312     my @attrs;
313     # keep a record of what we have seen
314     # here, this will handle all the 
315     # inheritence issues because we are 
316     # using the &class_precedence_list
317     my (%seen_class, %seen_attr);
318     foreach my $class ($self->class_precedence_list()) {
319         next if $seen_class{$class};
320         $seen_class{$class}++;
321         # fetch the meta-class ...
322         my $meta = $self->initialize($class);
323         foreach my $attr_name ($meta->get_attribute_list()) { 
324             next if exists $seen_attr{$attr_name};
325             $seen_attr{$attr_name}++;
326             push @attrs => {
327                 name      => $attr_name, 
328                 class     => $class,
329                 attribute => $meta->get_attribute($attr_name)
330             };
331         }
332     }
333     return @attrs;    
334 }
335
336 # Class attributes
337
338 sub add_package_variable {
339     my ($self, $variable, $initial_value) = @_;
340     (defined $variable && $variable =~ /^[\$\@\%]/)
341         || confess "variable name does not have a sigil";
342     
343     my ($sigil, $name) = ($variable =~ /^(.)(.*)$/); 
344     if (defined $initial_value) {
345         no strict 'refs';
346         *{$self->name . '::' . $name} = $initial_value;
347     }
348     else {
349         eval $sigil . $self->name . '::' . $name;
350         confess "Could not create package variable ($variable) because : $@" if $@;
351     }
352 }
353
354 sub has_package_variable {
355     my ($self, $variable) = @_;
356     (defined $variable && $variable =~ /^[\$\@\%]/)
357         || confess "variable name does not have a sigil";
358     my ($sigil, $name) = ($variable =~ /^(.)(.*)$/); 
359     no strict 'refs';
360     defined ${$self->name . '::'}{$name} ? 1 : 0;
361 }
362
363 sub get_package_variable {
364     my ($self, $variable) = @_;
365     (defined $variable && $variable =~ /^[\$\@\%]/)
366         || confess "variable name does not have a sigil";
367     my ($sigil, $name) = ($variable =~ /^(.)(.*)$/); 
368     no strict 'refs';
369     # try to fetch it first,.. see what happens
370     eval '\\' . $sigil . $self->name . '::' . $name;
371     confess "Could not get the package variable ($variable) because : $@" if $@;    
372     # if we didn't die, then we can return it
373     # NOTE:
374     # this is not ideal, better suggestions are welcome
375     eval '\\' . $sigil . $self->name . '::' . $name;   
376 }
377
378 sub remove_package_variable {
379     my ($self, $variable) = @_;
380     (defined $variable && $variable =~ /^[\$\@\%]/)
381         || confess "variable name does not have a sigil";
382     my ($sigil, $name) = ($variable =~ /^(.)(.*)$/); 
383     no strict 'refs';
384     delete ${$self->name . '::'}{$name};
385 }
386
387 1;
388
389 __END__
390
391 =pod
392
393 =head1 NAME 
394
395 Class::MOP::Class - Class Meta Object
396
397 =head1 SYNOPSIS
398
399   # use this for introspection ...
400   
401   package Foo;
402   sub meta { Class::MOP::Class->initialize(__PACKAGE__) }
403   
404   # elsewhere in the code ...
405   
406   # add a method to Foo ...
407   Foo->meta->add_method('bar' => sub { ... })
408   
409   # get a list of all the classes searched 
410   # the method dispatcher in the correct order 
411   Foo->meta->class_precedence_list()
412   
413   # remove a method from Foo
414   Foo->meta->remove_method('bar');
415   
416   # or use this to actually create classes ...
417   
418   Class::MOP::Class->create('Bar' => '0.01' => (
419       superclasses => [ 'Foo' ],
420       attributes => [
421           Class::MOP:::Attribute->new('$bar'),
422           Class::MOP:::Attribute->new('$baz'),          
423       ],
424       methods => {
425           calculate_bar => sub { ... },
426           construct_baz => sub { ... }          
427       }
428   ));
429
430 =head1 DESCRIPTION
431
432 This is the largest and currently most complex part of the Perl 5 
433 meta-object protocol. It controls the introspection and 
434 manipulation of Perl 5 classes (and it can create them too). The 
435 best way to understand what this module can do, is to read the 
436 documentation for each of it's methods.
437
438 =head1 METHODS
439
440 =head2 Self Introspection
441
442 =over 4
443
444 =item B<meta>
445
446 This will return a B<Class::MOP::Class> instance which is related 
447 to this class. Thereby allowing B<Class::MOP::Class> to actually 
448 introspect itself.
449
450 As with B<Class::MOP::Attribute>, B<Class::MOP> will actually 
451 bootstrap this module by installing a number of attribute meta-objects 
452 into it's metaclass. This will allow this class to reap all the benifits 
453 of the MOP when subclassing it. 
454
455 =back
456
457 =head2 Class construction
458
459 These methods will handle creating B<Class::MOP::Class> objects, 
460 which can be used to both create new classes, and analyze 
461 pre-existing classes. 
462
463 This module will internally store references to all the instances 
464 you create with these methods, so that they do not need to be 
465 created any more than nessecary. Basically, they are singletons.
466
467 =over 4
468
469 =item B<create ($package_name, ?$package_version,
470                 superclasses =E<gt> ?@superclasses, 
471                 methods      =E<gt> ?%methods, 
472                 attributes   =E<gt> ?%attributes)>
473
474 This returns a B<Class::MOP::Class> object, bringing the specified 
475 C<$package_name> into existence and adding any of the 
476 C<$package_version>, C<@superclasses>, C<%methods> and C<%attributes> 
477 to it.
478
479 =item B<initialize ($package_name)>
480
481 This initializes and returns returns a B<Class::MOP::Class> object 
482 for a given a C<$package_name>.
483
484 =item B<construct_class_instance ($package_name)>
485
486 This will construct an instance of B<Class::MOP::Class>, it is 
487 here so that we can actually "tie the knot" for B<Class::MOP::Class> 
488 to use C<construct_instance> once all the bootstrapping is done. This 
489 method is used internally by C<initialize> and should never be called
490 from outside of that method really.
491
492 =back
493
494 =head2 Object instance construction
495
496 This method is used to construct an instace structure suitable for 
497 C<bless>-ing into your package of choice. It works in conjunction 
498 with the Attribute protocol to collect all applicable attributes. 
499
500 This method is B<entirely optional>, it is up to you whether you want 
501 to use it or not.
502
503 =over 4
504
505 =item B<construct_instance (%params)>
506
507 This will construct and instance using a HASH ref as storage 
508 (currently only HASH references are supported). This will collect all 
509 the applicable attributes and layout out the fields in the HASH ref, 
510 it will then initialize them using either use the corresponding key 
511 in C<%params> or any default value or initializer found in the 
512 attribute meta-object.
513
514 =back
515
516 =head2 Informational 
517
518 =over 4
519
520 =item B<name>
521
522 This is a read-only attribute which returns the package name for the 
523 given B<Class::MOP::Class> instance.
524
525 =item B<version>
526
527 This is a read-only attribute which returns the C<$VERSION> of the 
528 package for the given B<Class::MOP::Class> instance.
529
530 =back
531
532 =head2 Inheritance Relationships
533
534 =over 4
535
536 =item B<superclasses (?@superclasses)>
537
538 This is a read-write attribute which represents the superclass 
539 relationships of the class the B<Class::MOP::Class> instance is
540 associated with. Basically, it can get and set the C<@ISA> for you.
541
542 =item B<class_precedence_list>
543
544 This computes the a list of all the class's ancestors in the same order 
545 in which method dispatch will be done. This is similair to 
546 what B<Class::ISA::super_path> does, but we don't remove duplicate names.
547
548 =back
549
550 =head2 Methods
551
552 =over 4
553
554 =item B<add_method ($method_name, $method)>
555
556 This will take a C<$method_name> and CODE reference to that 
557 C<$method> and install it into the class's package. 
558
559 B<NOTE>: 
560 This does absolutely nothing special to C<$method> 
561 other than use B<Sub::Name> to make sure it is tagged with the 
562 correct name, and therefore show up correctly in stack traces and 
563 such.
564
565 =item B<has_method ($method_name)>
566
567 This just provides a simple way to check if the class implements 
568 a specific C<$method_name>. It will I<not> however, attempt to check 
569 if the class inherits the method (use C<UNIVERSAL::can> for that).
570
571 This will correctly handle functions defined outside of the package 
572 that use a fully qualified name (C<sub Package::name { ... }>).
573
574 This will correctly handle functions renamed with B<Sub::Name> and 
575 installed using the symbol tables. However, if you are naming the 
576 subroutine outside of the package scope, you must use the fully 
577 qualified name, including the package name, for C<has_method> to 
578 correctly identify it. 
579
580 This will attempt to correctly ignore functions imported from other 
581 packages using B<Exporter>. It breaks down if the function imported 
582 is an C<__ANON__> sub (such as with C<use constant>), which very well 
583 may be a valid method being applied to the class. 
584
585 In short, this method cannot always be trusted to determine if the 
586 C<$method_name> is actually a method. However, it will DWIM about 
587 90% of the time, so it's a small trade off I think.
588
589 =item B<get_method ($method_name)>
590
591 This will return a CODE reference of the specified C<$method_name>, 
592 or return undef if that method does not exist.
593
594 =item B<remove_method ($method_name)>
595
596 This will attempt to remove a given C<$method_name> from the class. 
597 It will return the CODE reference that it has removed, and will 
598 attempt to use B<Sub::Name> to clear the methods associated name.
599
600 =item B<get_method_list>
601
602 This will return a list of method names for all I<locally> defined 
603 methods. It does B<not> provide a list of all applicable methods, 
604 including any inherited ones. If you want a list of all applicable 
605 methods, use the C<compute_all_applicable_methods> method.
606
607 =item B<compute_all_applicable_methods>
608
609 This will return a list of all the methods names this class will 
610 respond to, taking into account inheritance. The list will be a list of 
611 HASH references, each one containing the following information; method 
612 name, the name of the class in which the method lives and a CODE 
613 reference for the actual method.
614
615 =item B<find_all_methods_by_name ($method_name)>
616
617 This will traverse the inheritence hierarchy and locate all methods 
618 with a given C<$method_name>. Similar to 
619 C<compute_all_applicable_methods> it returns a list of HASH references 
620 with the following information; method name (which will always be the 
621 same as C<$method_name>), the name of the class in which the method 
622 lives and a CODE reference for the actual method.
623
624 The list of methods produced is a distinct list, meaning there are no 
625 duplicates in it. This is especially useful for things like object 
626 initialization and destruction where you only want the method called 
627 once, and in the correct order.
628
629 =back
630
631 =head2 Attributes
632
633 It should be noted that since there is no one consistent way to define 
634 the attributes of a class in Perl 5. These methods can only work with 
635 the information given, and can not easily discover information on 
636 their own. See L<Class::MOP::Attribute> for more details.
637
638 =over 4
639
640 =item B<add_attribute ($attribute_name, $attribute_meta_object)>
641
642 This stores a C<$attribute_meta_object> in the B<Class::MOP::Class> 
643 instance associated with the given class, and associates it with 
644 the C<$attribute_name>. Unlike methods, attributes within the MOP 
645 are stored as meta-information only. They will be used later to 
646 construct instances from (see C<construct_instance> above).
647 More details about the attribute meta-objects can be found in the 
648 L<Class::MOP::Attribute> or the L<Class::MOP/The Attribute protocol>
649 section.
650
651 It should be noted that any accessor, reader/writer or predicate 
652 methods which the C<$attribute_meta_object> has will be installed 
653 into the class at this time.
654
655 =item B<has_attribute ($attribute_name)>
656
657 Checks to see if this class has an attribute by the name of 
658 C<$attribute_name> and returns a boolean.
659
660 =item B<get_attribute ($attribute_name)>
661
662 Returns the attribute meta-object associated with C<$attribute_name>, 
663 if none is found, it will return undef. 
664
665 =item B<remove_attribute ($attribute_name)>
666
667 This will remove the attribute meta-object stored at 
668 C<$attribute_name>, then return the removed attribute meta-object. 
669
670 B<NOTE:> 
671 Removing an attribute will only affect future instances of 
672 the class, it will not make any attempt to remove the attribute from 
673 any existing instances of the class.
674
675 It should be noted that any accessor, reader/writer or predicate 
676 methods which the attribute meta-object stored at C<$attribute_name> 
677 has will be removed from the class at this time. This B<will> make 
678 these attributes somewhat inaccessable in previously created 
679 instances. But if you are crazy enough to do this at runtime, then 
680 you are crazy enough to deal with something like this :).
681
682 =item B<get_attribute_list>
683
684 This returns a list of attribute names which are defined in the local 
685 class. If you want a list of all applicable attributes for a class, 
686 use the C<compute_all_applicable_attributes> method.
687
688 =item B<compute_all_applicable_attributes>
689
690 This will traverse the inheritance heirachy and return a list of HASH 
691 references for all the applicable attributes for this class. The HASH 
692 references will contain the following information; the attribute name, 
693 the class which the attribute is associated with and the actual 
694 attribute meta-object.
695
696 =back
697
698 =head2 Package Variables
699
700 Since Perl's classes are built atop the Perl package system, it is 
701 fairly common to use package scoped variables for things like static 
702 class variables. The following methods are convience methods for 
703 the creation and inspection of package scoped variables.
704
705 =over 4
706
707 =item B<add_package_variable ($variable_name, ?$initial_value)>
708
709 Given a C<$variable_name>, which must contain a leading sigil, this 
710 method will create that variable within the package which houses the 
711 class. It also takes an optional C<$initial_value>, which must be a 
712 reference of the same type as the sigil of the C<$variable_name> 
713 implies.
714
715 =item B<get_package_variable ($variable_name)>
716
717 This will return a reference to the package variable in 
718 C<$variable_name>. 
719
720 =item B<has_package_variable ($variable_name)>
721
722 Returns true (C<1>) if there is a package variable defined for 
723 C<$variable_name>, and false (C<0>) otherwise.
724
725 =item B<remove_package_variable ($variable_name)>
726
727 This will attempt to remove the package variable at C<$variable_name>.
728
729 =back
730
731 =head1 AUTHOR
732
733 Stevan Little E<lt>stevan@iinteractive.comE<gt>
734
735 =head1 COPYRIGHT AND LICENSE
736
737 Copyright 2006 by Infinity Interactive, Inc.
738
739 L<http://www.iinteractive.com>
740
741 This library is free software; you can redistribute it and/or modify
742 it under the same terms as Perl itself. 
743
744 =cut