more stuff
[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
37 # meta-object instances. It will be replaces in
38 # the bootstrap section in Class::MOP with one
39 # which uses the 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 bless {
e16da3e6 45 '$:pkg' => $package_name,
46 '%:attrs' => {}
727919c5 47 } => blessed($class) || $class
bfe4d0fc 48 }
8b978dd5 49}
50
51sub create {
52 my ($class, $package_name, $package_version, %options) = @_;
bfe4d0fc 53 (defined $package_name && $package_name)
8b978dd5 54 || confess "You must pass a package name";
55 my $code = "package $package_name;";
56 $code .= "\$$package_name\:\:VERSION = '$package_version';"
57 if defined $package_version;
58 eval $code;
59 confess "creation of $package_name failed : $@" if $@;
bfe4d0fc 60 my $meta = $class->initialize($package_name);
8b978dd5 61 $meta->superclasses(@{$options{superclasses}})
62 if exists $options{superclasses};
2eb717d5 63 # NOTE:
64 # process attributes first, so that they can
65 # install accessors, but locally defined methods
66 # can then overwrite them. It is maybe a little odd, but
67 # I think this should be the order of things.
68 if (exists $options{attributes}) {
cbd9f942 69 foreach my $attr (@{$options{attributes}}) {
70 $meta->add_attribute($attr);
2eb717d5 71 }
72 }
bfe4d0fc 73 if (exists $options{methods}) {
74 foreach my $method_name (keys %{$options{methods}}) {
75 $meta->add_method($method_name, $options{methods}->{$method_name});
76 }
2eb717d5 77 }
8b978dd5 78 return $meta;
79}
80
e16da3e6 81# Instance Construction
82
83sub construct_instance {
cbd9f942 84 my ($class, %params) = @_;
85 my $instance = {};
86 foreach my $attr (map { $_->{attribute} } $class->compute_all_applicable_attributes()) {
87 # if the attr has an init_arg, use that, otherwise,
88 # use the attributes name itself as the init_arg
89 my $init_arg = $attr->has_init_arg() ? $attr->init_arg() : $attr->name;
90 # try to fetch the init arg from the %params ...
91 my $val;
92 $val = $params{$init_arg} if exists $params{$init_arg};
93 # if nothing was in the %params, we can use the
94 # attribute's default value (if it has one)
c50c603e 95 $val ||= $attr->default($instance) if $attr->has_default();
cbd9f942 96 # now add this to the instance structure
97 $instance->{$attr->name} = $val;
98 }
99 return $instance;
e16da3e6 100}
101
8b978dd5 102# Informational
103
e16da3e6 104sub name { $_[0]->{'$:pkg'} }
8b978dd5 105
106sub version {
107 my $self = shift;
108 no strict 'refs';
109 ${$self->name . '::VERSION'};
110}
111
112# Inheritance
113
114sub superclasses {
115 my $self = shift;
116 no strict 'refs';
117 if (@_) {
118 my @supers = @_;
119 @{$self->name . '::ISA'} = @supers;
120 }
121 @{$self->name . '::ISA'};
122}
123
124sub class_precedence_list {
125 my $self = shift;
bfe4d0fc 126 # NOTE:
127 # We need to check for ciruclar inheirtance here.
128 # This will do nothing if all is well, and blow
129 # up otherwise. Yes, it's an ugly hack, better
130 # suggestions are welcome.
131 { $self->name->isa('This is a test for circular inheritance') }
132 # ... and no back to our regularly scheduled program
8b978dd5 133 (
134 $self->name,
135 map {
bfe4d0fc 136 $self->initialize($_)->class_precedence_list()
8b978dd5 137 } $self->superclasses()
138 );
139}
140
0882828e 141## Methods
142
143sub add_method {
144 my ($self, $method_name, $method) = @_;
145 (defined $method_name && $method_name)
146 || confess "You must define a method name";
a5eca695 147 # use reftype here to allow for blessed subs ...
0882828e 148 (reftype($method) && reftype($method) eq 'CODE')
149 || confess "Your code block must be a CODE reference";
150 my $full_method_name = ($self->name . '::' . $method_name);
151
152 no strict 'refs';
c9b8b7f9 153 no warnings 'redefine';
0882828e 154 *{$full_method_name} = subname $full_method_name => $method;
155}
156
bfe4d0fc 157{
158
159 ## private utility functions for has_method
2eb717d5 160 my $_find_subroutine_package_name = sub { eval { svref_2object($_[0])->GV->STASH->NAME } || '' };
161 my $_find_subroutine_name = sub { eval { svref_2object($_[0])->GV->NAME } || '' };
bfe4d0fc 162
163 sub has_method {
c9b8b7f9 164 my ($self, $method_name) = @_;
bfe4d0fc 165 (defined $method_name && $method_name)
166 || confess "You must define a method name";
0882828e 167
bfe4d0fc 168 my $sub_name = ($self->name . '::' . $method_name);
0882828e 169
bfe4d0fc 170 no strict 'refs';
171 return 0 if !defined(&{$sub_name});
172 return 0 if $_find_subroutine_package_name->(\&{$sub_name}) ne $self->name &&
173 $_find_subroutine_name->(\&{$sub_name}) ne '__ANON__';
174 return 1;
175 }
176
0882828e 177}
178
179sub get_method {
c9b8b7f9 180 my ($self, $method_name) = @_;
0882828e 181 (defined $method_name && $method_name)
182 || confess "You must define a method name";
183
184 no strict 'refs';
185 return \&{$self->name . '::' . $method_name}
bfe4d0fc 186 if $self->has_method($method_name);
c9b8b7f9 187 return; # <- make sure to return undef
188}
189
190sub remove_method {
191 my ($self, $method_name) = @_;
192 (defined $method_name && $method_name)
193 || confess "You must define a method name";
194
195 my $removed_method = $self->get_method($method_name);
196
197 no strict 'refs';
198 delete ${$self->name . '::'}{$method_name}
199 if defined $removed_method;
200
201 return $removed_method;
202}
203
204sub get_method_list {
205 my $self = shift;
206 no strict 'refs';
a5eca695 207 grep { $self->has_method($_) } %{$self->name . '::'};
208}
209
210sub compute_all_applicable_methods {
211 my $self = shift;
212 my @methods;
213 # keep a record of what we have seen
214 # here, this will handle all the
215 # inheritence issues because we are
216 # using the &class_precedence_list
217 my (%seen_class, %seen_method);
218 foreach my $class ($self->class_precedence_list()) {
219 next if $seen_class{$class};
220 $seen_class{$class}++;
221 # fetch the meta-class ...
222 my $meta = $self->initialize($class);
223 foreach my $method_name ($meta->get_method_list()) {
224 next if exists $seen_method{$method_name};
225 $seen_method{$method_name}++;
226 push @methods => {
227 name => $method_name,
228 class => $class,
229 code => $meta->get_method($method_name)
230 };
231 }
232 }
233 return @methods;
234}
235
a5eca695 236sub find_all_methods_by_name {
237 my ($self, $method_name) = @_;
238 (defined $method_name && $method_name)
239 || confess "You must define a method name to find";
240 my @methods;
241 # keep a record of what we have seen
242 # here, this will handle all the
243 # inheritence issues because we are
244 # using the &class_precedence_list
245 my %seen_class;
246 foreach my $class ($self->class_precedence_list()) {
247 next if $seen_class{$class};
248 $seen_class{$class}++;
249 # fetch the meta-class ...
250 my $meta = $self->initialize($class);
251 push @methods => {
252 name => $method_name,
253 class => $class,
254 code => $meta->get_method($method_name)
255 } if $meta->has_method($method_name);
256 }
257 return @methods;
258
8b978dd5 259}
260
552e3d24 261## Attributes
262
e16da3e6 263sub add_attribute {
2eb717d5 264 my ($self,$attribute) = @_;
e16da3e6 265 (blessed($attribute) && $attribute->isa('Class::MOP::Attribute'))
266 || confess "Your attribute must be an instance of Class::MOP::Attribute (or a subclass)";
2eb717d5 267 $attribute->install_accessors($self);
268 $self->{'%:attrs'}->{$attribute->name} = $attribute;
e16da3e6 269}
270
271sub has_attribute {
272 my ($self, $attribute_name) = @_;
273 (defined $attribute_name && $attribute_name)
274 || confess "You must define an attribute name";
275 exists $self->{'%:attrs'}->{$attribute_name} ? 1 : 0;
276}
277
278sub get_attribute {
279 my ($self, $attribute_name) = @_;
280 (defined $attribute_name && $attribute_name)
281 || confess "You must define an attribute name";
282 return $self->{'%:attrs'}->{$attribute_name}
283 if $self->has_attribute($attribute_name);
284}
285
286sub remove_attribute {
287 my ($self, $attribute_name) = @_;
288 (defined $attribute_name && $attribute_name)
289 || confess "You must define an attribute name";
290 my $removed_attribute = $self->{'%:attrs'}->{$attribute_name};
291 delete $self->{'%:attrs'}->{$attribute_name}
292 if defined $removed_attribute;
2eb717d5 293 $removed_attribute->remove_accessors($self);
e16da3e6 294 return $removed_attribute;
295}
296
297sub get_attribute_list {
298 my $self = shift;
299 keys %{$self->{'%:attrs'}};
300}
301
302sub compute_all_applicable_attributes {
303 my $self = shift;
304 my @attrs;
305 # keep a record of what we have seen
306 # here, this will handle all the
307 # inheritence issues because we are
308 # using the &class_precedence_list
309 my (%seen_class, %seen_attr);
310 foreach my $class ($self->class_precedence_list()) {
311 next if $seen_class{$class};
312 $seen_class{$class}++;
313 # fetch the meta-class ...
314 my $meta = $self->initialize($class);
315 foreach my $attr_name ($meta->get_attribute_list()) {
316 next if exists $seen_attr{$attr_name};
317 $seen_attr{$attr_name}++;
318 push @attrs => {
319 name => $attr_name,
320 class => $class,
321 attribute => $meta->get_attribute($attr_name)
322 };
323 }
324 }
325 return @attrs;
326}
2eb717d5 327
8b978dd5 3281;
329
330__END__
331
332=pod
333
334=head1 NAME
335
336Class::MOP::Class - Class Meta Object
337
338=head1 SYNOPSIS
339
340=head1 DESCRIPTION
341
552e3d24 342=head1 METHODS
343
2eb717d5 344=head2 Self Introspection
345
346=over 4
347
348=item B<meta>
349
350This allows Class::MOP::Class to actually introspect itself.
351
352=back
353
552e3d24 354=head2 Class construction
355
356These methods handle creating Class objects, which can be used to
357both create new classes, and analyze pre-existing ones.
358
359This module will internally store references to all the instances
360you create with these methods, so that they do not need to be
361created any more than nessecary. Basically, they are singletons.
362
363=over 4
364
365=item B<create ($package_name, ?$package_version,
366 superclasses => ?@superclasses,
367 methods => ?%methods,
368 attributes => ?%attributes)>
369
370This returns the basic Class object, bringing the specified
371C<$package_name> into existence and adding any of the
372C<$package_version>, C<@superclasses>, C<%methods> and C<%attributes>
373to it.
374
375=item B<initialize ($package_name)>
376
377This initializes a Class object for a given a C<$package_name>.
378
379=back
380
381=head2 Instance construction
382
383=over 4
384
cbd9f942 385=item B<construct_instance (%params)>
552e3d24 386
cbd9f942 387This will construct and instance using a HASH ref as storage
552e3d24 388(currently only HASH references are supported). This will collect all
389the applicable attribute meta-objects and layout out the fields in the
cbd9f942 390HASH ref, it will then initialize them using either use the
552e3d24 391corresponding key in C<%params> or any default value or initializer
392found in the attribute meta-object.
393
727919c5 394=item B<construct_class_instance ($package_name)>
395
396This will construct an instance of B<Class::MOP::Class>, it is
397here so that we can actually "tie the knot" for B<Class::MOP::Class>
398to use C<construct_instance> once all the bootstrapping is done. This
399method is used internally by C<initialize> and should never be called
400from outside of that method really.
401
552e3d24 402=back
403
404=head2 Informational
405
406=over 4
407
408=item B<name>
409
410This is a read-only attribute which returns the package name that
411the Class is stored in.
412
413=item B<version>
414
415This is a read-only attribute which returns the C<$VERSION> of the
416package the Class is stored in.
417
418=back
419
420=head2 Inheritance Relationships
421
422=over 4
423
424=item B<superclasses (?@superclasses)>
425
426This is a read-write attribute which represents the superclass
427relationships of this Class. Basically, it can get and set the
428C<@ISA> for you.
429
430=item B<class_precedence_list>
431
432This computes the a list of the Class's ancestors in the same order
433in which method dispatch will be done.
434
435=back
436
437=head2 Methods
438
439=over 4
440
441=item B<add_method ($method_name, $method)>
442
443This will take a C<$method_name> and CODE reference to that
444C<$method> and install it into the Class.
445
446B<NOTE> : This does absolutely nothing special to C<$method>
447other than use B<Sub::Name> to make sure it is tagged with the
448correct name, and therefore show up correctly in stack traces and
449such.
450
451=item B<has_method ($method_name)>
452
453This just provides a simple way to check if the Class implements
454a specific C<$method_name>. It will I<not> however, attempt to check
455if the class inherits the method.
456
457This will correctly handle functions defined outside of the package
458that use a fully qualified name (C<sub Package::name { ... }>).
459
460This will correctly handle functions renamed with B<Sub::Name> and
461installed using the symbol tables. However, if you are naming the
462subroutine outside of the package scope, you must use the fully
463qualified name, including the package name, for C<has_method> to
464correctly identify it.
465
466This will attempt to correctly ignore functions imported from other
467packages using B<Exporter>. It breaks down if the function imported
468is an C<__ANON__> sub (such as with C<use constant>), which very well
469may be a valid method being applied to the class.
470
471In short, this method cannot always be trusted to determine if the
472C<$method_name> is actually a method. However, it will DWIM about
47390% of the time, so it's a small trade off IMO.
474
475=item B<get_method ($method_name)>
476
477This will return a CODE reference of the specified C<$method_name>,
478or return undef if that method does not exist.
479
480=item B<remove_method ($method_name)>
481
482This will attempt to remove a given C<$method_name> from the Class.
483It will return the CODE reference that it has removed, and will
484attempt to use B<Sub::Name> to clear the methods associated name.
485
486=item B<get_method_list>
487
488This will return a list of method names for all I<locally> defined
489methods. It does B<not> provide a list of all applicable methods,
490including any inherited ones. If you want a list of all applicable
491methods, use the C<compute_all_applicable_methods> method.
492
493=item B<compute_all_applicable_methods>
494
495This will return a list of all the methods names this Class will
496support, taking into account inheritance. The list will be a list of
497HASH references, each one containing the following information; method
498name, the name of the class in which the method lives and a CODE
499reference for the actual method.
500
501=item B<find_all_methods_by_name ($method_name)>
502
503This will traverse the inheritence hierarchy and locate all methods
504with a given C<$method_name>. Similar to
505C<compute_all_applicable_methods> it returns a list of HASH references
506with the following information; method name (which will always be the
507same as C<$method_name>), the name of the class in which the method
508lives and a CODE reference for the actual method.
509
510The list of methods produced is a distinct list, meaning there are no
511duplicates in it. This is especially useful for things like object
512initialization and destruction where you only want the method called
513once, and in the correct order.
514
515=back
516
517=head2 Attributes
518
519It should be noted that since there is no one consistent way to define
520the attributes of a class in Perl 5. These methods can only work with
521the information given, and can not easily discover information on
522their own.
523
524=over 4
525
526=item B<add_attribute ($attribute_name, $attribute_meta_object)>
527
528This stores a C<$attribute_meta_object> in the Class object and
529associates it with the C<$attribute_name>. Unlike methods, attributes
530within the MOP are stored as meta-information only. They will be used
531later to construct instances from (see C<construct_instance> above).
532More details about the attribute meta-objects can be found in the
533L<The Attribute protocol> section of this document.
534
535=item B<has_attribute ($attribute_name)>
536
537Checks to see if this Class has an attribute by the name of
538C<$attribute_name> and returns a boolean.
539
540=item B<get_attribute ($attribute_name)>
541
542Returns the attribute meta-object associated with C<$attribute_name>,
543if none is found, it will return undef.
544
545=item B<remove_attribute ($attribute_name)>
546
547This will remove the attribute meta-object stored at
548C<$attribute_name>, then return the removed attribute meta-object.
549
550B<NOTE:> Removing an attribute will only affect future instances of
551the class, it will not make any attempt to remove the attribute from
552any existing instances of the class.
553
554=item B<get_attribute_list>
555
556This returns a list of attribute names which are defined in the local
557class. If you want a list of all applicable attributes for a class,
558use the C<compute_all_applicable_attributes> method.
559
560=item B<compute_all_applicable_attributes>
561
562This will traverse the inheritance heirachy and return a list of HASH
563references for all the applicable attributes for this class. The HASH
564references will contain the following information; the attribute name,
565the class which the attribute is associated with and the actual
2eb717d5 566attribute meta-object.
552e3d24 567
568=back
569
8b978dd5 570=head1 AUTHOR
571
572Stevan Little E<gt>stevan@iinteractive.comE<lt>
573
574=head1 COPYRIGHT AND LICENSE
575
576Copyright 2006 by Infinity Interactive, Inc.
577
578L<http://www.iinteractive.com>
579
580This library is free software; you can redistribute it and/or modify
581it under the same terms as Perl itself.
582
583=cut