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