Inside out class example, and many other tweaks
[gitmo/Class-MOP.git] / lib / Class / MOP / Class.pm
CommitLineData
8b978dd5 1
2package Class::MOP::Class;
3
4use strict;
5use warnings;
6
7use Carp 'confess';
0882828e 8use Scalar::Util 'blessed', 'reftype';
8b978dd5 9use Sub::Name 'subname';
10use B 'svref_2object';
11
12our $VERSION = '0.01';
13
2eb717d5 14# Self-introspection
15
16sub meta { $_[0]->initialize($_[0]) }
17
8b978dd5 18# Creation
19
bfe4d0fc 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)
727919c5 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
1a7ebbb3 37 # meta-object instances for any Class::MOP::*
38 # class. All other classes will use the more
39 # normal &construct_instance.
727919c5 40 sub construct_class_instance {
41 my ($class, $package_name) = @_;
42 (defined $package_name && $package_name)
1a7ebbb3 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 }
bfe4d0fc 54 }
8b978dd5 55}
56
57sub create {
58 my ($class, $package_name, $package_version, %options) = @_;
bfe4d0fc 59 (defined $package_name && $package_name)
8b978dd5 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 $@;
bfe4d0fc 66 my $meta = $class->initialize($package_name);
8b978dd5 67 $meta->superclasses(@{$options{superclasses}})
68 if exists $options{superclasses};
2eb717d5 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}) {
cbd9f942 75 foreach my $attr (@{$options{attributes}}) {
76 $meta->add_attribute($attr);
2eb717d5 77 }
78 }
bfe4d0fc 79 if (exists $options{methods}) {
80 foreach my $method_name (keys %{$options{methods}}) {
81 $meta->add_method($method_name, $options{methods}->{$method_name});
82 }
2eb717d5 83 }
8b978dd5 84 return $meta;
85}
86
e16da3e6 87# Instance Construction
88
89sub construct_instance {
cbd9f942 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)
c50c603e 101 $val ||= $attr->default($instance) if $attr->has_default();
cbd9f942 102 # now add this to the instance structure
103 $instance->{$attr->name} = $val;
104 }
105 return $instance;
e16da3e6 106}
107
8b978dd5 108# Informational
109
e16da3e6 110sub name { $_[0]->{'$:pkg'} }
8b978dd5 111
112sub version {
113 my $self = shift;
114 no strict 'refs';
115 ${$self->name . '::VERSION'};
116}
117
118# Inheritance
119
120sub 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
130sub class_precedence_list {
131 my $self = shift;
bfe4d0fc 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
8b978dd5 139 (
140 $self->name,
141 map {
bfe4d0fc 142 $self->initialize($_)->class_precedence_list()
8b978dd5 143 } $self->superclasses()
144 );
145}
146
0882828e 147## Methods
148
149sub add_method {
150 my ($self, $method_name, $method) = @_;
151 (defined $method_name && $method_name)
152 || confess "You must define a method name";
a5eca695 153 # use reftype here to allow for blessed subs ...
0882828e 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';
c9b8b7f9 159 no warnings 'redefine';
0882828e 160 *{$full_method_name} = subname $full_method_name => $method;
161}
162
bfe4d0fc 163{
164
165 ## private utility functions for has_method
2eb717d5 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 } || '' };
bfe4d0fc 168
169 sub has_method {
c9b8b7f9 170 my ($self, $method_name) = @_;
bfe4d0fc 171 (defined $method_name && $method_name)
172 || confess "You must define a method name";
0882828e 173
bfe4d0fc 174 my $sub_name = ($self->name . '::' . $method_name);
0882828e 175
bfe4d0fc 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
0882828e 183}
184
185sub get_method {
c9b8b7f9 186 my ($self, $method_name) = @_;
0882828e 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}
bfe4d0fc 192 if $self->has_method($method_name);
c9b8b7f9 193 return; # <- make sure to return undef
194}
195
196sub 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
210sub get_method_list {
211 my $self = shift;
212 no strict 'refs';
a5eca695 213 grep { $self->has_method($_) } %{$self->name . '::'};
214}
215
216sub 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
a5eca695 242sub 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
8b978dd5 265}
266
552e3d24 267## Attributes
268
e16da3e6 269sub add_attribute {
2eb717d5 270 my ($self,$attribute) = @_;
e16da3e6 271 (blessed($attribute) && $attribute->isa('Class::MOP::Attribute'))
272 || confess "Your attribute must be an instance of Class::MOP::Attribute (or a subclass)";
2eb717d5 273 $attribute->install_accessors($self);
274 $self->{'%:attrs'}->{$attribute->name} = $attribute;
e16da3e6 275}
276
277sub has_attribute {
278 my ($self, $attribute_name) = @_;
279 (defined $attribute_name && $attribute_name)
280 || confess "You must define an attribute name";
281 exists $self->{'%:attrs'}->{$attribute_name} ? 1 : 0;
282}
283
284sub get_attribute {
285 my ($self, $attribute_name) = @_;
286 (defined $attribute_name && $attribute_name)
287 || confess "You must define an attribute name";
288 return $self->{'%:attrs'}->{$attribute_name}
289 if $self->has_attribute($attribute_name);
290}
291
292sub remove_attribute {
293 my ($self, $attribute_name) = @_;
294 (defined $attribute_name && $attribute_name)
295 || confess "You must define an attribute name";
296 my $removed_attribute = $self->{'%:attrs'}->{$attribute_name};
297 delete $self->{'%:attrs'}->{$attribute_name}
298 if defined $removed_attribute;
2eb717d5 299 $removed_attribute->remove_accessors($self);
e16da3e6 300 return $removed_attribute;
301}
302
303sub get_attribute_list {
304 my $self = shift;
305 keys %{$self->{'%:attrs'}};
306}
307
308sub compute_all_applicable_attributes {
309 my $self = shift;
310 my @attrs;
311 # keep a record of what we have seen
312 # here, this will handle all the
313 # inheritence issues because we are
314 # using the &class_precedence_list
315 my (%seen_class, %seen_attr);
316 foreach my $class ($self->class_precedence_list()) {
317 next if $seen_class{$class};
318 $seen_class{$class}++;
319 # fetch the meta-class ...
320 my $meta = $self->initialize($class);
321 foreach my $attr_name ($meta->get_attribute_list()) {
322 next if exists $seen_attr{$attr_name};
323 $seen_attr{$attr_name}++;
324 push @attrs => {
325 name => $attr_name,
326 class => $class,
327 attribute => $meta->get_attribute($attr_name)
328 };
329 }
330 }
331 return @attrs;
332}
2eb717d5 333
52e8a34c 334# Class attributes
335
336sub add_package_variable {
337 my ($self, $variable, $initial_value) = @_;
338 (defined $variable && $variable =~ /^[\$\@\%]/)
339 || confess "variable name does not have a sigil";
340
341 my ($sigil, $name) = ($variable =~ /^(.)(.*)$/);
342 if (defined $initial_value) {
343 no strict 'refs';
344 *{$self->name . '::' . $name} = $initial_value;
345 }
346 else {
347 eval $sigil . $self->name . '::' . $name;
348 confess "Could not create package variable ($variable) because : $@" if $@;
349 }
350}
351
352sub has_package_variable {
353 my ($self, $variable) = @_;
354 (defined $variable && $variable =~ /^[\$\@\%]/)
355 || confess "variable name does not have a sigil";
356 my ($sigil, $name) = ($variable =~ /^(.)(.*)$/);
357 no strict 'refs';
358 defined ${$self->name . '::'}{$name} ? 1 : 0;
359}
360
361sub get_package_variable {
362 my ($self, $variable) = @_;
363 (defined $variable && $variable =~ /^[\$\@\%]/)
364 || confess "variable name does not have a sigil";
365 my ($sigil, $name) = ($variable =~ /^(.)(.*)$/);
366 no strict 'refs';
367 # try to fetch it first,.. see what happens
368 eval '\\' . $sigil . $self->name . '::' . $name;
369 confess "Could not get the package variable ($variable) because : $@" if $@;
370 # if we didn't die, then we can return it
371 # NOTE:
372 # this is not ideal, better suggestions are welcome
373 eval '\\' . $sigil . $self->name . '::' . $name;
374}
375
376sub remove_package_variable {
377 my ($self, $variable) = @_;
378 (defined $variable && $variable =~ /^[\$\@\%]/)
379 || confess "variable name does not have a sigil";
380 my ($sigil, $name) = ($variable =~ /^(.)(.*)$/);
381 no strict 'refs';
382 delete ${$self->name . '::'}{$name};
383}
384
8b978dd5 3851;
386
387__END__
388
389=pod
390
391=head1 NAME
392
393Class::MOP::Class - Class Meta Object
394
395=head1 SYNOPSIS
396
fe122940 397 # use this for introspection ...
398
399 package Foo;
400 sub meta { Class::MOP::Class->initialize(__PACKAGE__) }
401
402 # elsewhere in the code ...
403
404 # add a method to Foo ...
405 Foo->meta->add_method('bar' => sub { ... })
406
407 # get a list of all the classes searched
408 # the method dispatcher in the correct order
409 Foo->meta->class_precedence_list()
410
411 # remove a method from Foo
412 Foo->meta->remove_method('bar');
413
414 # or use this to actually create classes ...
415
416 Class::MOP::Class->create('Bar' => '0.01' => (
417 superclasses => [ 'Foo' ],
418 attributes => [
419 Class::MOP:::Attribute->new('$bar'),
420 Class::MOP:::Attribute->new('$baz'),
421 ],
422 methods => {
423 calculate_bar => sub { ... },
424 construct_baz => sub { ... }
425 }
426 ));
427
8b978dd5 428=head1 DESCRIPTION
429
fe122940 430This is the largest and currently most complex part of the Perl 5
431meta-object protocol. It controls the introspection and
432manipulation of Perl 5 classes (and it can create them too). The
433best way to understand what this module can do, is to read the
434documentation for each of it's methods.
435
552e3d24 436=head1 METHODS
437
2eb717d5 438=head2 Self Introspection
439
440=over 4
441
442=item B<meta>
443
fe122940 444This will return a B<Class::MOP::Class> instance which is related
445to this class. Thereby allowing B<Class::MOP::Class> to actually
446introspect itself.
447
448As with B<Class::MOP::Attribute>, B<Class::MOP> will actually
449bootstrap this module by installing a number of attribute meta-objects
450into it's metaclass. This will allow this class to reap all the benifits
451of the MOP when subclassing it.
2eb717d5 452
453=back
454
552e3d24 455=head2 Class construction
456
457These methods handle creating Class objects, which can be used to
458both create new classes, and analyze pre-existing ones.
459
460This module will internally store references to all the instances
461you create with these methods, so that they do not need to be
462created any more than nessecary. Basically, they are singletons.
463
464=over 4
465
466=item B<create ($package_name, ?$package_version,
467 superclasses => ?@superclasses,
468 methods => ?%methods,
469 attributes => ?%attributes)>
470
471This returns the basic Class object, bringing the specified
472C<$package_name> into existence and adding any of the
473C<$package_version>, C<@superclasses>, C<%methods> and C<%attributes>
474to it.
475
476=item B<initialize ($package_name)>
477
478This initializes a Class object for a given a C<$package_name>.
479
480=back
481
482=head2 Instance construction
483
484=over 4
485
cbd9f942 486=item B<construct_instance (%params)>
552e3d24 487
cbd9f942 488This will construct and instance using a HASH ref as storage
552e3d24 489(currently only HASH references are supported). This will collect all
490the applicable attribute meta-objects and layout out the fields in the
cbd9f942 491HASH ref, it will then initialize them using either use the
552e3d24 492corresponding key in C<%params> or any default value or initializer
493found in the attribute meta-object.
494
727919c5 495=item B<construct_class_instance ($package_name)>
496
497This will construct an instance of B<Class::MOP::Class>, it is
498here so that we can actually "tie the knot" for B<Class::MOP::Class>
499to use C<construct_instance> once all the bootstrapping is done. This
500method is used internally by C<initialize> and should never be called
501from outside of that method really.
502
552e3d24 503=back
504
505=head2 Informational
506
507=over 4
508
509=item B<name>
510
511This is a read-only attribute which returns the package name that
512the Class is stored in.
513
514=item B<version>
515
516This is a read-only attribute which returns the C<$VERSION> of the
517package the Class is stored in.
518
519=back
520
521=head2 Inheritance Relationships
522
523=over 4
524
525=item B<superclasses (?@superclasses)>
526
527This is a read-write attribute which represents the superclass
528relationships of this Class. Basically, it can get and set the
529C<@ISA> for you.
530
531=item B<class_precedence_list>
532
533This computes the a list of the Class's ancestors in the same order
534in which method dispatch will be done.
535
536=back
537
538=head2 Methods
539
540=over 4
541
542=item B<add_method ($method_name, $method)>
543
544This will take a C<$method_name> and CODE reference to that
545C<$method> and install it into the Class.
546
547B<NOTE> : This does absolutely nothing special to C<$method>
548other than use B<Sub::Name> to make sure it is tagged with the
549correct name, and therefore show up correctly in stack traces and
550such.
551
552=item B<has_method ($method_name)>
553
554This just provides a simple way to check if the Class implements
555a specific C<$method_name>. It will I<not> however, attempt to check
556if the class inherits the method.
557
558This will correctly handle functions defined outside of the package
559that use a fully qualified name (C<sub Package::name { ... }>).
560
561This will correctly handle functions renamed with B<Sub::Name> and
562installed using the symbol tables. However, if you are naming the
563subroutine outside of the package scope, you must use the fully
564qualified name, including the package name, for C<has_method> to
565correctly identify it.
566
567This will attempt to correctly ignore functions imported from other
568packages using B<Exporter>. It breaks down if the function imported
569is an C<__ANON__> sub (such as with C<use constant>), which very well
570may be a valid method being applied to the class.
571
572In short, this method cannot always be trusted to determine if the
573C<$method_name> is actually a method. However, it will DWIM about
57490% of the time, so it's a small trade off IMO.
575
576=item B<get_method ($method_name)>
577
578This will return a CODE reference of the specified C<$method_name>,
579or return undef if that method does not exist.
580
581=item B<remove_method ($method_name)>
582
583This will attempt to remove a given C<$method_name> from the Class.
584It will return the CODE reference that it has removed, and will
585attempt to use B<Sub::Name> to clear the methods associated name.
586
587=item B<get_method_list>
588
589This will return a list of method names for all I<locally> defined
590methods. It does B<not> provide a list of all applicable methods,
591including any inherited ones. If you want a list of all applicable
592methods, use the C<compute_all_applicable_methods> method.
593
594=item B<compute_all_applicable_methods>
595
596This will return a list of all the methods names this Class will
597support, taking into account inheritance. The list will be a list of
598HASH references, each one containing the following information; method
599name, the name of the class in which the method lives and a CODE
600reference for the actual method.
601
602=item B<find_all_methods_by_name ($method_name)>
603
604This will traverse the inheritence hierarchy and locate all methods
605with a given C<$method_name>. Similar to
606C<compute_all_applicable_methods> it returns a list of HASH references
607with the following information; method name (which will always be the
608same as C<$method_name>), the name of the class in which the method
609lives and a CODE reference for the actual method.
610
611The list of methods produced is a distinct list, meaning there are no
612duplicates in it. This is especially useful for things like object
613initialization and destruction where you only want the method called
614once, and in the correct order.
615
616=back
617
618=head2 Attributes
619
620It should be noted that since there is no one consistent way to define
621the attributes of a class in Perl 5. These methods can only work with
622the information given, and can not easily discover information on
623their own.
624
625=over 4
626
627=item B<add_attribute ($attribute_name, $attribute_meta_object)>
628
629This stores a C<$attribute_meta_object> in the Class object and
630associates it with the C<$attribute_name>. Unlike methods, attributes
631within the MOP are stored as meta-information only. They will be used
632later to construct instances from (see C<construct_instance> above).
633More details about the attribute meta-objects can be found in the
634L<The Attribute protocol> section of this document.
635
636=item B<has_attribute ($attribute_name)>
637
638Checks to see if this Class has an attribute by the name of
639C<$attribute_name> and returns a boolean.
640
641=item B<get_attribute ($attribute_name)>
642
643Returns the attribute meta-object associated with C<$attribute_name>,
644if none is found, it will return undef.
645
646=item B<remove_attribute ($attribute_name)>
647
648This will remove the attribute meta-object stored at
649C<$attribute_name>, then return the removed attribute meta-object.
650
651B<NOTE:> Removing an attribute will only affect future instances of
652the class, it will not make any attempt to remove the attribute from
653any existing instances of the class.
654
655=item B<get_attribute_list>
656
657This returns a list of attribute names which are defined in the local
658class. If you want a list of all applicable attributes for a class,
659use the C<compute_all_applicable_attributes> method.
660
661=item B<compute_all_applicable_attributes>
662
663This will traverse the inheritance heirachy and return a list of HASH
664references for all the applicable attributes for this class. The HASH
665references will contain the following information; the attribute name,
666the class which the attribute is associated with and the actual
2eb717d5 667attribute meta-object.
552e3d24 668
669=back
670
52e8a34c 671=head2 Package Variables
672
673Since Perl's classes are built atop the Perl package system, it is
674fairly common to use package scoped variables for things like static
675class variables. The following methods are convience methods for
676the creation and inspection of package scoped variables.
677
678=over 4
679
680=item B<add_package_variable ($variable_name, ?$initial_value)>
681
682Given a C<$variable_name>, which must contain a leading sigil, this
683method will create that variable within the package which houses the
684class. It also takes an optional C<$initial_value>, which must be a
685reference of the same type as the sigil of the C<$variable_name>
686implies.
687
688=item B<get_package_variable ($variable_name)>
689
690This will return a reference to the package variable in
691C<$variable_name>.
692
693=item B<has_package_variable ($variable_name)>
694
695Returns true (C<1>) if there is a package variable defined for
696C<$variable_name>, and false (C<0>) otherwise.
697
698=item B<remove_package_variable ($variable_name)>
699
700This will attempt to remove the package variable at C<$variable_name>.
701
702=back
703
8b978dd5 704=head1 AUTHOR
705
706Stevan Little E<gt>stevan@iinteractive.comE<lt>
707
708=head1 COPYRIGHT AND LICENSE
709
710Copyright 2006 by Infinity Interactive, Inc.
711
712L<http://www.iinteractive.com>
713
714This library is free software; you can redistribute it and/or modify
715it under the same terms as Perl itself.
716
717=cut