lots of documentation changes, some refactoring too
[gitmo/Class-MOP.git] / lib / Class / MOP.pm
1
2 package Class::MOP;
3
4 use strict;
5 use warnings;
6
7 use Carp         'confess';
8 use Scalar::Util 'weaken';
9
10 use Class::MOP::Class;
11 use Class::MOP::Attribute;
12 use Class::MOP::Method;
13
14 use Class::MOP::Class::Immutable;
15
16 our $VERSION   = '0.33';
17 our $AUTHORITY = 'cpan:STEVAN';
18
19 {
20     # Metaclasses are singletons, so we cache them here.
21     # there is no need to worry about destruction though
22     # because they should die only when the program dies.
23     # After all, do package definitions even get reaped?
24     my %METAS;  
25     
26     # means of accessing all the metaclasses that have 
27     # been initialized thus far (for mugwumps obj browser)
28     sub get_all_metaclasses         {        %METAS         }            
29     sub get_all_metaclass_instances { values %METAS         } 
30     sub get_all_metaclass_names     { keys   %METAS         }     
31     sub get_metaclass_by_name       { $METAS{$_[0]}         }
32     sub store_metaclass_by_name     { $METAS{$_[0]} = $_[1] }  
33     sub weaken_metaclass            { weaken($METAS{$_[0]}) }            
34     sub does_metaclass_exist        { exists $METAS{$_[0]} && defined $METAS{$_[0]} }
35     sub remove_metaclass_by_name    { $METAS{$_[0]} = undef }     
36     
37     # NOTE:
38     # We only cache metaclasses, meaning instances of 
39     # Class::MOP::Class. We do not cache instance of 
40     # Class::MOP::Package or Class::MOP::Module. Mostly
41     # because I don't yet see a good reason to do so.        
42 }
43
44 ## ----------------------------------------------------------------------------
45 ## Setting up our environment ...
46 ## ----------------------------------------------------------------------------
47 ## Class::MOP needs to have a few things in the global perl environment so 
48 ## that it can operate effectively. Those things are done here.
49 ## ----------------------------------------------------------------------------
50
51 # ... nothing yet actually ;)
52
53 ## ----------------------------------------------------------------------------
54 ## Bootstrapping 
55 ## ----------------------------------------------------------------------------
56 ## The code below here is to bootstrap our MOP with itself. This is also 
57 ## sometimes called "tying the knot". By doing this, we make it much easier
58 ## to extend the MOP through subclassing and such since now you can use the
59 ## MOP itself to extend itself. 
60 ## 
61 ## Yes, I know, thats weird and insane, but it's a good thing, trust me :)
62 ## ---------------------------------------------------------------------------- 
63
64 # We need to add in the meta-attributes here so that 
65 # any subclass of Class::MOP::* will be able to 
66 # inherit them using &construct_instance
67
68 ## --------------------------------------------------------
69 ## Class::MOP::Package
70
71 Class::MOP::Package->meta->add_attribute(
72     Class::MOP::Attribute->new('$:package' => (
73         reader   => {
74             # NOTE: we need to do this in order 
75             # for the instance meta-object to 
76             # not fall into meta-circular death
77             'name' => sub { (shift)->{'$:package'} }
78         },
79         init_arg => ':package',
80     ))
81 );
82
83 Class::MOP::Package->meta->add_attribute(
84     Class::MOP::Attribute->new('%:namespace' => (
85         reader => {
86             'namespace' => sub { (shift)->{'%:namespace'} }
87         },
88         default => sub {
89             my ($class) = @_;
90             no strict 'refs';
91             return \%{$class->name . '::'};
92         },
93         # NOTE:
94         # protect this from silliness 
95         init_arg => '!............( DO NOT DO THIS )............!',
96     ))
97 );
98
99 # NOTE:
100 # use the metaclass to construct the meta-package
101 # which is a superclass of the metaclass itself :P
102 Class::MOP::Package->meta->add_method('initialize' => sub {
103     my $class        = shift;
104     my $package_name = shift;
105     $class->meta->new_object(':package' => $package_name, @_);  
106 });
107
108 ## --------------------------------------------------------
109 ## Class::MOP::Module
110
111 # NOTE:
112 # yeah this is kind of stretching things a bit, 
113 # but truthfully the version should be an attribute
114 # of the Module, the weirdness comes from having to 
115 # stick to Perl 5 convention and store it in the 
116 # $VERSION package variable. Basically if you just 
117 # squint at it, it will look how you want it to look. 
118 # Either as a package variable, or as a attribute of
119 # the metaclass, isn't abstraction great :)
120
121 Class::MOP::Module->meta->add_attribute(
122     Class::MOP::Attribute->new('$:version' => (
123         reader => {
124             'version' => sub {  
125                 my $self = shift;
126                 ${$self->get_package_symbol('$VERSION')};
127             }
128         },
129         # NOTE:
130         # protect this from silliness 
131         init_arg => '!............( DO NOT DO THIS )............!',
132     ))
133 );
134
135 # NOTE:
136 # By following the same conventions as version here, 
137 # we are opening up the possibility that people can 
138 # use the $AUTHORITY in non-Class::MOP modules as 
139 # well.  
140
141 Class::MOP::Module->meta->add_attribute(
142     Class::MOP::Attribute->new('$:authority' => (
143         reader => {
144             'authority' => sub {  
145                 my $self = shift;
146                 ${$self->get_package_symbol('$AUTHORITY')};
147             }
148         },       
149         # NOTE:
150         # protect this from silliness 
151         init_arg => '!............( DO NOT DO THIS )............!',
152     ))
153 );
154
155 ## --------------------------------------------------------
156 ## Class::MOP::Class
157
158 Class::MOP::Class->meta->add_attribute(
159     Class::MOP::Attribute->new('%:attributes' => (
160         reader   => {
161             # NOTE: we need to do this in order 
162             # for the instance meta-object to 
163             # not fall into meta-circular death            
164             'get_attribute_map' => sub { (shift)->{'%:attributes'} }
165         },
166         init_arg => ':attributes',
167         default  => sub { {} }
168     ))
169 );
170
171 Class::MOP::Class->meta->add_attribute(
172     Class::MOP::Attribute->new('$:attribute_metaclass' => (
173         reader   => 'attribute_metaclass',
174         init_arg => ':attribute_metaclass',
175         default  => 'Class::MOP::Attribute',
176     ))
177 );
178
179 Class::MOP::Class->meta->add_attribute(
180     Class::MOP::Attribute->new('$:method_metaclass' => (
181         reader   => 'method_metaclass',
182         init_arg => ':method_metaclass',
183         default  => 'Class::MOP::Method',        
184     ))
185 );
186
187 Class::MOP::Class->meta->add_attribute(
188     Class::MOP::Attribute->new('$:instance_metaclass' => (
189         reader   => {
190             # NOTE: we need to do this in order 
191             # for the instance meta-object to 
192             # not fall into meta-circular death            
193             'instance_metaclass' => sub { (shift)->{'$:instance_metaclass'} }
194         },
195         init_arg => ':instance_metaclass',
196         default  => 'Class::MOP::Instance',        
197     ))
198 );
199
200 # NOTE:
201 # we don't actually need to tie the knot with 
202 # Class::MOP::Class here, it is actually handled 
203 # within Class::MOP::Class itself in the 
204 # construct_class_instance method. 
205
206 ## --------------------------------------------------------
207 ## Class::MOP::Attribute
208
209 Class::MOP::Attribute->meta->add_attribute(
210     Class::MOP::Attribute->new('name' => (
211         reader => {
212             # NOTE: we need to do this in order 
213             # for the instance meta-object to 
214             # not fall into meta-circular death            
215             'name' => sub { (shift)->{name} }
216         }
217     ))
218 );
219
220 Class::MOP::Attribute->meta->add_attribute(
221     Class::MOP::Attribute->new('associated_class' => (
222         reader => {
223             # NOTE: we need to do this in order 
224             # for the instance meta-object to 
225             # not fall into meta-circular death            
226             'associated_class' => sub { (shift)->{associated_class} }
227         }
228     ))
229 );
230
231 Class::MOP::Attribute->meta->add_attribute(
232     Class::MOP::Attribute->new('accessor' => (
233         reader    => 'accessor',
234         predicate => 'has_accessor',
235     ))
236 );
237
238 Class::MOP::Attribute->meta->add_attribute(
239     Class::MOP::Attribute->new('reader' => (
240         reader    => 'reader',
241         predicate => 'has_reader',
242     ))
243 );
244
245 Class::MOP::Attribute->meta->add_attribute(
246     Class::MOP::Attribute->new('writer' => (
247         reader    => 'writer',
248         predicate => 'has_writer',
249     ))
250 );
251
252 Class::MOP::Attribute->meta->add_attribute(
253     Class::MOP::Attribute->new('predicate' => (
254         reader    => 'predicate',
255         predicate => 'has_predicate',
256     ))
257 );
258
259 Class::MOP::Attribute->meta->add_attribute(
260     Class::MOP::Attribute->new('clearer' => (
261         reader    => 'clearer',
262         predicate => 'has_clearer',
263     ))
264 );
265
266 Class::MOP::Attribute->meta->add_attribute(
267     Class::MOP::Attribute->new('init_arg' => (
268         reader    => 'init_arg',
269         predicate => 'has_init_arg',
270     ))
271 );
272
273 Class::MOP::Attribute->meta->add_attribute(
274     Class::MOP::Attribute->new('default' => (
275         # default has a custom 'reader' method ...
276         predicate => 'has_default',
277     ))
278 );
279
280
281 # NOTE: (meta-circularity)
282 # This should be one of the last things done
283 # it will "tie the knot" with Class::MOP::Attribute
284 # so that it uses the attributes meta-objects 
285 # to construct itself. 
286 Class::MOP::Attribute->meta->add_method('new' => sub {
287     my $class   = shift;
288     my $name    = shift;
289     my %options = @_;    
290         
291     (defined $name && $name)
292         || confess "You must provide a name for the attribute";
293     $options{init_arg} = $name 
294         if not exists $options{init_arg};
295         
296     (Class::MOP::Attribute::is_default_a_coderef(\%options))
297         || confess("References are not allowed as default values, you must ". 
298                    "wrap then in a CODE reference (ex: sub { [] } and not [])")
299             if exists $options{default} && ref $options{default};        
300
301     # return the new object
302     $class->meta->new_object(name => $name, %options);
303 });
304
305 Class::MOP::Attribute->meta->add_method('clone' => sub {
306     my $self  = shift;
307     $self->meta->clone_object($self, @_);  
308 });
309
310 ## --------------------------------------------------------
311 ## Now close all the Class::MOP::* classes
312
313 Class::MOP::Package  ->meta->make_immutable(inline_constructor => 0);
314 Class::MOP::Module   ->meta->make_immutable(inline_constructor => 0);
315 Class::MOP::Class    ->meta->make_immutable(inline_constructor => 0);
316 Class::MOP::Attribute->meta->make_immutable(inline_constructor => 0);
317 Class::MOP::Method   ->meta->make_immutable(inline_constructor => 0);
318 Class::MOP::Instance ->meta->make_immutable(inline_constructor => 0);
319 Class::MOP::Object   ->meta->make_immutable(inline_constructor => 0);
320
321 1;
322
323 __END__
324
325 =pod
326
327 =head1 NAME 
328
329 Class::MOP - A Meta Object Protocol for Perl 5
330
331 =head1 SYNOPSIS
332
333   # ... This will come later, for now see
334   # the other SYNOPSIS for more information
335
336 =head1 DESCRIPTON
337
338 This module is an attempt to create a meta object protocol for the 
339 Perl 5 object system. It makes no attempt to change the behavior or 
340 characteristics of the Perl 5 object system, only to create a 
341 protocol for its manipulation and introspection.
342
343 That said, it does attempt to create the tools for building a rich 
344 set of extensions to the Perl 5 object system. Every attempt has been 
345 made for these tools to keep to the spirit of the Perl 5 object 
346 system that we all know and love.
347
348 This documentation is admittedly sparse on details, as time permits 
349 I will try to improve them. For now, I suggest looking at the items 
350 listed in the L<SEE ALSO> section for more information. In particular 
351 the book "The Art of the Meta Object Protocol" was very influential 
352 in the development of this system.
353
354 =head2 What is a Meta Object Protocol?
355
356 A meta object protocol is an API to an object system. 
357
358 To be more specific, it is a set of abstractions of the components of 
359 an object system (typically things like; classes, object, methods, 
360 object attributes, etc.). These abstractions can then be used to both 
361 inspect and manipulate the object system which they describe.
362
363 It can be said that there are two MOPs for any object system; the 
364 implicit MOP, and the explicit MOP. The implicit MOP handles things 
365 like method dispatch or inheritance, which happen automatically as 
366 part of how the object system works. The explicit MOP typically 
367 handles the introspection/reflection features of the object system. 
368 All object systems have implicit MOPs, without one, they would not 
369 work. Explict MOPs however as less common, and depending on the 
370 language can vary from restrictive (Reflection in Java or C#) to 
371 wide open (CLOS is a perfect example). 
372
373 =head2 Yet Another Class Builder!! Why?
374
375 This is B<not> a class builder so much as it is a I<class builder 
376 B<builder>>. My intent is that an end user does not use this module 
377 directly, but instead this module is used by module authors to 
378 build extensions and features onto the Perl 5 object system. 
379
380 =head2 Who is this module for?
381
382 This module is specifically for anyone who has ever created or 
383 wanted to create a module for the Class:: namespace. The tools which 
384 this module will provide will hopefully make it easier to do more 
385 complex things with Perl 5 classes by removing such barriers as 
386 the need to hack the symbol tables, or understand the fine details 
387 of method dispatch. 
388
389 =head2 What changes do I have to make to use this module?
390
391 This module was designed to be as unintrusive as possible. Many of 
392 its features are accessible without B<any> change to your existsing 
393 code at all. It is meant to be a compliment to your existing code and 
394 not an intrusion on your code base. Unlike many other B<Class::> 
395 modules, this module B<does not> require you subclass it, or even that 
396 you C<use> it in within your module's package. 
397
398 The only features which requires additions to your code are the 
399 attribute handling and instance construction features, and these are
400 both completely optional features. The only reason for this is because 
401 Perl 5's object system does not actually have these features built 
402 in. More information about this feature can be found below.
403
404 =head2 A Note about Performance?
405
406 It is a common misconception that explict MOPs are performance drains. 
407 But this is not a universal truth at all, it is an side-effect of 
408 specific implementations. For instance, using Java reflection is much 
409 slower because the JVM cannot take advantage of any compiler 
410 optimizations, and the JVM has to deal with much more runtime type 
411 information as well. Reflection in C# is marginally better as it was 
412 designed into the language and runtime (the CLR). In contrast, CLOS 
413 (the Common Lisp Object System) was built to support an explicit MOP, 
414 and so performance is tuned for it. 
415
416 This library in particular does it's absolute best to avoid putting 
417 B<any> drain at all upon your code's performance. In fact, by itself 
418 it does nothing to affect your existing code. So you only pay for 
419 what you actually use.
420
421 =head2 About Metaclass compatibility
422
423 This module makes sure that all metaclasses created are both upwards 
424 and downwards compatible. The topic of metaclass compatibility is 
425 highly esoteric and is something only encountered when doing deep and 
426 involved metaclass hacking. There are two basic kinds of metaclass 
427 incompatibility; upwards and downwards. 
428
429 Upwards metaclass compatibility means that the metaclass of a 
430 given class is either the same as (or a subclass of) all of the 
431 class's ancestors.
432
433 Downward metaclass compatibility means that the metaclasses of a 
434 given class's anscestors are all either the same as (or a subclass 
435 of) that metaclass.
436
437 Here is a diagram showing a set of two classes (C<A> and C<B>) and 
438 two metaclasses (C<Meta::A> and C<Meta::B>) which have correct  
439 metaclass compatibility both upwards and downwards.
440
441     +---------+     +---------+
442     | Meta::A |<----| Meta::B |      <....... (instance of  )
443     +---------+     +---------+      <------- (inherits from)  
444          ^               ^
445          :               :
446     +---------+     +---------+
447     |    A    |<----|    B    |
448     +---------+     +---------+
449
450 As I said this is a highly esoteric topic and one you will only run 
451 into if you do a lot of subclassing of B<Class::MOP::Class>. If you 
452 are interested in why this is an issue see the paper 
453 I<Uniform and safe metaclass composition> linked to in the 
454 L<SEE ALSO> section of this document.
455
456 =head2 Using custom metaclasses
457
458 Always use the metaclass pragma when using a custom metaclass, this 
459 will ensure the proper initialization order and not accidentely 
460 create an incorrect type of metaclass for you. This is a very rare 
461 problem, and one which can only occur if you are doing deep metaclass 
462 programming. So in other words, don't worry about it.
463
464 =head1 PROTOCOLS
465
466 The protocol is divided into 3 main sub-protocols:
467
468 =over 4
469
470 =item The Class protocol
471
472 This provides a means of manipulating and introspecting a Perl 5 
473 class. It handles all of symbol table hacking for you, and provides 
474 a rich set of methods that go beyond simple package introspection.
475
476 See L<Class::MOP::Class> for more details.
477
478 =item The Attribute protocol
479
480 This provides a consistent represenation for an attribute of a 
481 Perl 5 class. Since there are so many ways to create and handle 
482 atttributes in Perl 5 OO, this attempts to provide as much of a 
483 unified approach as possible, while giving the freedom and 
484 flexibility to subclass for specialization.
485
486 See L<Class::MOP::Attribute> for more details.
487
488 =item The Method protocol
489
490 This provides a means of manipulating and introspecting methods in 
491 the Perl 5 object system. As with attributes, there are many ways to 
492 approach this topic, so we try to keep it pretty basic, while still 
493 making it possible to extend the system in many ways.
494
495 See L<Class::MOP::Method> for more details.
496
497 =back
498
499 =head1 FUNCTIONS
500
501 Class::MOP holds a cache of metaclasses, the following are functions 
502 (B<not methods>) which can be used to access that cache. It is not 
503 recommended that you mess with this, bad things could happen. But if 
504 you are brave and willing to risk it, go for it.
505
506 =over 4
507
508 =item B<get_all_metaclasses>
509
510 This will return an hash of all the metaclass instances that have 
511 been cached by B<Class::MOP::Class> keyed by the package name. 
512
513 =item B<get_all_metaclass_instances>
514
515 This will return an array of all the metaclass instances that have 
516 been cached by B<Class::MOP::Class>.
517
518 =item B<get_all_metaclass_names>
519
520 This will return an array of all the metaclass names that have 
521 been cached by B<Class::MOP::Class>.
522
523 =item B<get_metaclass_by_name ($name)>
524
525 =item B<store_metaclass_by_name ($name, $meta)>
526
527 =item B<weaken_metaclass ($name)>
528
529 =item B<does_metaclass_exist ($name)>
530
531 =item B<remove_metaclass_by_name ($name)>
532
533 =back
534
535 =head1 SEE ALSO
536
537 =head2 Books
538
539 There are very few books out on Meta Object Protocols and Metaclasses 
540 because it is such an esoteric topic. The following books are really 
541 the only ones I have found. If you know of any more, B<I<please>> 
542 email me and let me know, I would love to hear about them.
543
544 =over 4
545
546 =item "The Art of the Meta Object Protocol"
547
548 =item "Advances in Object-Oriented Metalevel Architecture and Reflection"
549
550 =item "Putting MetaClasses to Work"
551
552 =item "Smalltalk: The Language"
553
554 =back
555
556 =head2 Papers
557
558 =over 4
559
560 =item Uniform and safe metaclass composition
561
562 An excellent paper by the people who brought us the original Traits paper. 
563 This paper is on how Traits can be used to do safe metaclass composition, 
564 and offers an excellent introduction section which delves into the topic of 
565 metaclass compatibility.
566
567 L<http://www.iam.unibe.ch/~scg/Archive/Papers/Duca05ySafeMetaclassTrait.pdf>
568
569 =item Safe Metaclass Programming
570
571 This paper seems to precede the above paper, and propose a mix-in based 
572 approach as opposed to the Traits based approach. Both papers have similar 
573 information on the metaclass compatibility problem space. 
574
575 L<http://citeseer.ist.psu.edu/37617.html>
576
577 =back
578
579 =head2 Prior Art
580
581 =over 4
582
583 =item The Perl 6 MetaModel work in the Pugs project
584
585 =over 4
586
587 =item L<http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel>
588
589 =item L<http://svn.openfoundry.org/pugs/perl5/Perl6-ObjectSpace>
590
591 =back
592
593 =back
594
595 =head1 SIMILAR MODULES
596
597 As I have said above, this module is a class-builder-builder, so it is 
598 not the same thing as modules like L<Class::Accessor> and 
599 L<Class::MethodMaker>. That being said there are very few modules on CPAN 
600 with similar goals to this module. The one I have found which is most 
601 like this module is L<Class::Meta>, although it's philosophy and the MOP it 
602 creates are very different from this modules. 
603
604 =head1 BUGS
605
606 All complex software has bugs lurking in it, and this module is no 
607 exception. If you find a bug please either email me, or add the bug
608 to cpan-RT.
609
610 =head1 CODE COVERAGE
611
612 I use L<Devel::Cover> to test the code coverage of my tests, below is the 
613 L<Devel::Cover> report on this module's test suite.
614
615  ---------------------------- ------ ------ ------ ------ ------ ------ ------
616  File                           stmt   bran   cond    sub    pod   time  total
617  ---------------------------- ------ ------ ------ ------ ------ ------ ------
618  Class/MOP.pm                   78.0   87.5   55.6   71.4  100.0   12.4   76.8
619  Class/MOP/Attribute.pm         83.4   75.6   86.7   94.4  100.0    8.9   85.2
620  Class/MOP/Class.pm             96.9   75.8   43.2   98.0  100.0   55.3   83.6
621  Class/MOP/Class/Immutable.pm   88.5   53.8    n/a   95.8  100.0    1.1   84.7
622  Class/MOP/Instance.pm          87.9   75.0   33.3   89.7  100.0   10.1   89.1
623  Class/MOP/Method.pm            97.6   60.0   57.9   76.9  100.0    1.5   82.8
624  Class/MOP/Module.pm            87.5    n/a   11.1   83.3  100.0    0.3   66.7
625  Class/MOP/Object.pm           100.0    n/a   33.3  100.0  100.0    0.1   89.5
626  Class/MOP/Package.pm           95.1   69.0   33.3  100.0  100.0    9.9   85.5
627  metaclass.pm                  100.0  100.0   83.3  100.0    n/a    0.5   97.7
628  ---------------------------- ------ ------ ------ ------ ------ ------ ------
629  Total                          91.5   72.1   48.8   90.7  100.0  100.0   84.2
630  ---------------------------- ------ ------ ------ ------ ------ ------ ------
631
632 =head1 ACKNOWLEDGEMENTS
633
634 =over 4
635
636 =item Rob Kinyon
637
638 Thanks to Rob for actually getting the development of this module kick-started. 
639
640 =back
641
642 =head1 AUTHORS
643
644 Stevan Little E<lt>stevan@iinteractive.comE<gt>
645
646 Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
647
648 =head1 COPYRIGHT AND LICENSE
649
650 Copyright 2006 by Infinity Interactive, Inc.
651
652 L<http://www.iinteractive.com>
653
654 This library is free software; you can redistribute it and/or modify
655 it under the same terms as Perl itself. 
656
657 =cut