merging the immutable branch into trunk
[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::Immutable;
15
16 our $VERSION   = '0.37';
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             # 
78             # we just alias the original method
79             # rather than re-produce it here            
80             'name' => \&Class::MOP::Package::name
81         },
82         init_arg => 'package',
83     ))
84 );
85
86 Class::MOP::Package->meta->add_attribute(
87     Class::MOP::Attribute->new('%!namespace' => (
88         reader => {
89             # NOTE:
90             # we just alias the original method
91             # rather than re-produce it here
92             'namespace' => \&Class::MOP::Package::namespace
93         },
94         # NOTE:
95         # protect this from silliness 
96         init_arg => '!............( DO NOT DO THIS )............!',
97         default  => sub { \undef }
98     ))
99 );
100
101 # NOTE:
102 # use the metaclass to construct the meta-package
103 # which is a superclass of the metaclass itself :P
104 Class::MOP::Package->meta->add_method('initialize' => sub {
105     my $class        = shift;
106     my $package_name = shift;
107     $class->meta->new_object('package' => $package_name, @_);  
108 });
109
110 ## --------------------------------------------------------
111 ## Class::MOP::Module
112
113 # NOTE:
114 # yeah this is kind of stretching things a bit, 
115 # but truthfully the version should be an attribute
116 # of the Module, the weirdness comes from having to 
117 # stick to Perl 5 convention and store it in the 
118 # $VERSION package variable. Basically if you just 
119 # squint at it, it will look how you want it to look. 
120 # Either as a package variable, or as a attribute of
121 # the metaclass, isn't abstraction great :)
122
123 Class::MOP::Module->meta->add_attribute(
124     Class::MOP::Attribute->new('$!version' => (
125         reader => {
126             # NOTE:
127             # we just alias the original method
128             # rather than re-produce it here            
129             'version' => \&Class::MOP::Module::version
130         },
131         # NOTE:
132         # protect this from silliness 
133         init_arg => '!............( DO NOT DO THIS )............!',
134         default  => sub { \undef }
135     ))
136 );
137
138 # NOTE:
139 # By following the same conventions as version here, 
140 # we are opening up the possibility that people can 
141 # use the $AUTHORITY in non-Class::MOP modules as 
142 # well.  
143
144 Class::MOP::Module->meta->add_attribute(
145     Class::MOP::Attribute->new('$!authority' => (
146         reader => {
147             # NOTE:
148             # we just alias the original method
149             # rather than re-produce it here            
150             'authority' => \&Class::MOP::Module::authority
151         },       
152         # NOTE:
153         # protect this from silliness 
154         init_arg => '!............( DO NOT DO THIS )............!',
155         default  => sub { \undef }
156     ))
157 );
158
159 ## --------------------------------------------------------
160 ## Class::MOP::Class
161
162 Class::MOP::Class->meta->add_attribute(
163     Class::MOP::Attribute->new('%!attributes' => (
164         reader   => {
165             # NOTE: we need to do this in order 
166             # for the instance meta-object to 
167             # not fall into meta-circular death       
168             # 
169             # we just alias the original method
170             # rather than re-produce it here                 
171             'get_attribute_map' => \&Class::MOP::Class::get_attribute_map
172         },
173         init_arg => 'attributes',
174         default  => sub { {} }
175     ))
176 );
177
178 Class::MOP::Class->meta->add_attribute(
179     Class::MOP::Attribute->new('%!methods' => (
180         init_arg => 'methods',
181         reader   => {          
182             # NOTE:
183             # we just alias the original method
184             # rather than re-produce it here            
185             'get_method_map' => \&Class::MOP::Class::get_method_map
186         },
187         default => sub { {} }
188     ))
189 );
190
191 Class::MOP::Class->meta->add_attribute(
192     Class::MOP::Attribute->new('@!superclasses' => (
193         accessor => {
194             # NOTE:
195             # we just alias the original method
196             # rather than re-produce it here            
197             'superclasses' => \&Class::MOP::Class::superclasses
198         },
199         # NOTE:
200         # protect this from silliness 
201         init_arg => '!............( DO NOT DO THIS )............!',
202         default  => sub { \undef }
203     ))
204 );
205
206 Class::MOP::Class->meta->add_attribute(
207     Class::MOP::Attribute->new('$!attribute_metaclass' => (
208         reader   => {          
209             # NOTE:
210             # we just alias the original method
211             # rather than re-produce it here            
212             'attribute_metaclass' => \&Class::MOP::Class::attribute_metaclass
213         },        
214         init_arg => 'attribute_metaclass',
215         default  => 'Class::MOP::Attribute',
216     ))
217 );
218
219 Class::MOP::Class->meta->add_attribute(
220     Class::MOP::Attribute->new('$!method_metaclass' => (
221         reader   => {          
222             # NOTE:
223             # we just alias the original method
224             # rather than re-produce it here            
225             'method_metaclass' => \&Class::MOP::Class::method_metaclass
226         },
227         init_arg => 'method_metaclass',
228         default  => 'Class::MOP::Method',        
229     ))
230 );
231
232 Class::MOP::Class->meta->add_attribute(
233     Class::MOP::Attribute->new('$!instance_metaclass' => (
234         reader   => {
235             # NOTE: we need to do this in order 
236             # for the instance meta-object to 
237             # not fall into meta-circular death      
238             # 
239             # we just alias the original method
240             # rather than re-produce it here                  
241             'instance_metaclass' => \&Class::MOP::Class::instance_metaclass
242         },
243         init_arg => 'instance_metaclass',
244         default  => 'Class::MOP::Instance',        
245     ))
246 );
247
248 # NOTE:
249 # we don't actually need to tie the knot with 
250 # Class::MOP::Class here, it is actually handled 
251 # within Class::MOP::Class itself in the 
252 # construct_class_instance method. 
253
254 ## --------------------------------------------------------
255 ## Class::MOP::Attribute
256
257 Class::MOP::Attribute->meta->add_attribute(
258     Class::MOP::Attribute->new('$!name' => (
259         init_arg => 'name',
260         reader   => {
261             # NOTE: we need to do this in order 
262             # for the instance meta-object to 
263             # not fall into meta-circular death    
264             # 
265             # we just alias the original method
266             # rather than re-produce it here                    
267             'name' => \&Class::MOP::Attribute::name
268         }
269     ))
270 );
271
272 Class::MOP::Attribute->meta->add_attribute(
273     Class::MOP::Attribute->new('$!associated_class' => (
274         init_arg => 'associated_class',
275         reader   => {
276             # NOTE: we need to do this in order 
277             # for the instance meta-object to 
278             # not fall into meta-circular death       
279             # 
280             # we just alias the original method
281             # rather than re-produce it here                 
282             'associated_class' => \&Class::MOP::Attribute::associated_class
283         }
284     ))
285 );
286
287 Class::MOP::Attribute->meta->add_attribute(
288     Class::MOP::Attribute->new('$!accessor' => (
289         init_arg  => 'accessor',
290         reader    => { 'accessor'     => \&Class::MOP::Attribute::accessor     },
291         predicate => { 'has_accessor' => \&Class::MOP::Attribute::has_accessor },
292     ))
293 );
294
295 Class::MOP::Attribute->meta->add_attribute(
296     Class::MOP::Attribute->new('$!reader' => (
297         init_arg  => 'reader',
298         reader    => { 'reader'     => \&Class::MOP::Attribute::reader     },
299         predicate => { 'has_reader' => \&Class::MOP::Attribute::has_reader },
300     ))
301 );
302
303 Class::MOP::Attribute->meta->add_attribute(
304     Class::MOP::Attribute->new('$!writer' => (
305         init_arg  => 'writer',
306         reader    => { 'writer'     => \&Class::MOP::Attribute::writer     },
307         predicate => { 'has_writer' => \&Class::MOP::Attribute::has_writer },
308     ))
309 );
310
311 Class::MOP::Attribute->meta->add_attribute(
312     Class::MOP::Attribute->new('$!predicate' => (
313         init_arg  => 'predicate',
314         reader    => { 'predicate'     => \&Class::MOP::Attribute::predicate     },
315         predicate => { 'has_predicate' => \&Class::MOP::Attribute::has_predicate },
316     ))
317 );
318
319 Class::MOP::Attribute->meta->add_attribute(
320     Class::MOP::Attribute->new('$!clearer' => (
321         init_arg  => 'clearer',
322         reader    => { 'clearer'     => \&Class::MOP::Attribute::clearer     },
323         predicate => { 'has_clearer' => \&Class::MOP::Attribute::has_clearer },
324     ))
325 );
326
327 Class::MOP::Attribute->meta->add_attribute(
328     Class::MOP::Attribute->new('$!init_arg' => (
329         init_arg  => 'init_arg',
330         reader    => { 'init_arg'     => \&Class::MOP::Attribute::init_arg     },
331         predicate => { 'has_init_arg' => \&Class::MOP::Attribute::has_init_arg },
332     ))
333 );
334
335 Class::MOP::Attribute->meta->add_attribute(
336     Class::MOP::Attribute->new('$!default' => (
337         init_arg  => 'default',
338         # default has a custom 'reader' method ...
339         predicate => { 'has_default' => \&Class::MOP::Attribute::has_default },        
340     ))
341 );
342
343 Class::MOP::Attribute->meta->add_attribute(
344     Class::MOP::Attribute->new('@!associated_methods' => (
345         init_arg => 'associated_methods',
346         reader   => { 'associated_methods' => \&Class::MOP::Attribute::associated_methods },
347         default  => sub { [] } 
348     ))
349 );
350
351 # NOTE: (meta-circularity)
352 # This should be one of the last things done
353 # it will "tie the knot" with Class::MOP::Attribute
354 # so that it uses the attributes meta-objects 
355 # to construct itself. 
356 Class::MOP::Attribute->meta->add_method('new' => sub {
357     my $class   = shift;
358     my $name    = shift;
359     my %options = @_;    
360         
361     (defined $name && $name)
362         || confess "You must provide a name for the attribute";
363     $options{init_arg} = $name 
364         if not exists $options{init_arg};
365         
366     (Class::MOP::Attribute::is_default_a_coderef(\%options))
367         || confess("References are not allowed as default values, you must ". 
368                    "wrap then in a CODE reference (ex: sub { [] } and not [])")
369             if exists $options{default} && ref $options{default};        
370
371     # return the new object
372     $class->meta->new_object(name => $name, %options);
373 });
374
375 Class::MOP::Attribute->meta->add_method('clone' => sub {
376     my $self  = shift;
377     $self->meta->clone_object($self, @_);  
378 });
379
380 ## --------------------------------------------------------
381 ## Class::MOP::Method
382
383 Class::MOP::Method->meta->add_attribute(
384     Class::MOP::Attribute->new('&!body' => (
385         init_arg => 'body',
386         reader   => { 'body' => \&Class::MOP::Method::body },
387     ))
388 );
389
390 ## --------------------------------------------------------
391 ## Class::MOP::Method::Wrapped
392
393 # NOTE:
394 # the way this item is initialized, this 
395 # really does not follow the standard 
396 # practices of attributes, but we put 
397 # it here for completeness
398 Class::MOP::Method::Wrapped->meta->add_attribute(
399     Class::MOP::Attribute->new('%!modifier_table')
400 );
401
402 ## --------------------------------------------------------
403 ## Class::MOP::Method::Accessor
404
405 Class::MOP::Method::Accessor->meta->add_attribute(
406     Class::MOP::Attribute->new('$!attribute' => (
407         init_arg => 'attribute',
408         reader   => { 
409             'associated_attribute' => \&Class::MOP::Method::Accessor::associated_attribute 
410         },
411     ))    
412 );
413
414 Class::MOP::Method::Accessor->meta->add_attribute(
415     Class::MOP::Attribute->new('$!accessor_type' => (
416         init_arg => 'accessor_type',
417         reader   => { 'accessor_type' => \&Class::MOP::Method::Accessor::accessor_type },
418     ))    
419 );
420
421 Class::MOP::Method::Accessor->meta->add_attribute(
422     Class::MOP::Attribute->new('$!is_inline' => (
423         init_arg => 'is_inline',
424         reader   => { 'is_inline' => \&Class::MOP::Method::Accessor::is_inline },
425     ))    
426 );
427
428 ## --------------------------------------------------------
429 ## Class::MOP::Method::Constructor
430
431 Class::MOP::Method::Constructor->meta->add_attribute(
432     Class::MOP::Attribute->new('%!options' => (
433         init_arg => 'options',
434         reader   => { 
435             'options' => \&Class::MOP::Method::Constructor::options 
436         },
437     ))    
438 );
439
440 Class::MOP::Method::Constructor->meta->add_attribute(
441     Class::MOP::Attribute->new('$!associated_metaclass' => (
442         init_arg => 'metaclass',
443         reader   => { 
444             'associated_metaclass' => \&Class::MOP::Method::Constructor::associated_metaclass 
445         },        
446     ))    
447 );
448
449 ## --------------------------------------------------------
450 ## Class::MOP::Instance
451
452 # NOTE:
453 # these don't yet do much of anything, but are just 
454 # included for completeness
455
456 Class::MOP::Instance->meta->add_attribute(
457     Class::MOP::Attribute->new('$!meta')
458 );
459
460 Class::MOP::Instance->meta->add_attribute(
461     Class::MOP::Attribute->new('@!slots')
462 );
463
464 ## --------------------------------------------------------
465 ## Now close all the Class::MOP::* classes
466
467 # NOTE:
468 # we don't need to inline the 
469 # constructors or the accessors 
470 # this only lengthens the compile 
471 # time of the MOP, and gives us 
472 # no actual benefits.
473
474 $_->meta->make_immutable(
475     inline_constructor => 0,
476     inline_accessors   => 0,
477 ) for qw/
478     Class::MOP::Package  
479     Class::MOP::Module   
480     Class::MOP::Class    
481     
482     Class::MOP::Attribute
483     Class::MOP::Method   
484     Class::MOP::Instance 
485     
486     Class::MOP::Object   
487
488     Class::MOP::Method::Accessor
489     Class::MOP::Method::Constructor    
490     Class::MOP::Method::Wrapped           
491 /;
492
493 1;
494
495 __END__
496
497 =pod
498
499 =head1 NAME 
500
501 Class::MOP - A Meta Object Protocol for Perl 5
502
503 =head1 SYNOPSIS
504
505   # ... This will come later, for now see
506   # the other SYNOPSIS for more information
507
508 =head1 DESCRIPTON
509
510 This module is an attempt to create a meta object protocol for the 
511 Perl 5 object system. It makes no attempt to change the behavior or 
512 characteristics of the Perl 5 object system, only to create a 
513 protocol for its manipulation and introspection.
514
515 That said, it does attempt to create the tools for building a rich 
516 set of extensions to the Perl 5 object system. Every attempt has been 
517 made for these tools to keep to the spirit of the Perl 5 object 
518 system that we all know and love.
519
520 This documentation is admittedly sparse on details, as time permits 
521 I will try to improve them. For now, I suggest looking at the items 
522 listed in the L<SEE ALSO> section for more information. In particular 
523 the book "The Art of the Meta Object Protocol" was very influential 
524 in the development of this system.
525
526 =head2 What is a Meta Object Protocol?
527
528 A meta object protocol is an API to an object system. 
529
530 To be more specific, it is a set of abstractions of the components of 
531 an object system (typically things like; classes, object, methods, 
532 object attributes, etc.). These abstractions can then be used to both 
533 inspect and manipulate the object system which they describe.
534
535 It can be said that there are two MOPs for any object system; the 
536 implicit MOP, and the explicit MOP. The implicit MOP handles things 
537 like method dispatch or inheritance, which happen automatically as 
538 part of how the object system works. The explicit MOP typically 
539 handles the introspection/reflection features of the object system. 
540 All object systems have implicit MOPs, without one, they would not 
541 work. Explict MOPs however as less common, and depending on the 
542 language can vary from restrictive (Reflection in Java or C#) to 
543 wide open (CLOS is a perfect example). 
544
545 =head2 Yet Another Class Builder!! Why?
546
547 This is B<not> a class builder so much as it is a I<class builder 
548 B<builder>>. My intent is that an end user does not use this module 
549 directly, but instead this module is used by module authors to 
550 build extensions and features onto the Perl 5 object system. 
551
552 =head2 Who is this module for?
553
554 This module is specifically for anyone who has ever created or 
555 wanted to create a module for the Class:: namespace. The tools which 
556 this module will provide will hopefully make it easier to do more 
557 complex things with Perl 5 classes by removing such barriers as 
558 the need to hack the symbol tables, or understand the fine details 
559 of method dispatch. 
560
561 =head2 What changes do I have to make to use this module?
562
563 This module was designed to be as unintrusive as possible. Many of 
564 its features are accessible without B<any> change to your existsing 
565 code at all. It is meant to be a compliment to your existing code and 
566 not an intrusion on your code base. Unlike many other B<Class::> 
567 modules, this module B<does not> require you subclass it, or even that 
568 you C<use> it in within your module's package. 
569
570 The only features which requires additions to your code are the 
571 attribute handling and instance construction features, and these are
572 both completely optional features. The only reason for this is because 
573 Perl 5's object system does not actually have these features built 
574 in. More information about this feature can be found below.
575
576 =head2 A Note about Performance?
577
578 It is a common misconception that explict MOPs are performance drains. 
579 But this is not a universal truth at all, it is an side-effect of 
580 specific implementations. For instance, using Java reflection is much 
581 slower because the JVM cannot take advantage of any compiler 
582 optimizations, and the JVM has to deal with much more runtime type 
583 information as well. Reflection in C# is marginally better as it was 
584 designed into the language and runtime (the CLR). In contrast, CLOS 
585 (the Common Lisp Object System) was built to support an explicit MOP, 
586 and so performance is tuned for it. 
587
588 This library in particular does it's absolute best to avoid putting 
589 B<any> drain at all upon your code's performance. In fact, by itself 
590 it does nothing to affect your existing code. So you only pay for 
591 what you actually use.
592
593 =head2 About Metaclass compatibility
594
595 This module makes sure that all metaclasses created are both upwards 
596 and downwards compatible. The topic of metaclass compatibility is 
597 highly esoteric and is something only encountered when doing deep and 
598 involved metaclass hacking. There are two basic kinds of metaclass 
599 incompatibility; upwards and downwards. 
600
601 Upwards metaclass compatibility means that the metaclass of a 
602 given class is either the same as (or a subclass of) all of the 
603 class's ancestors.
604
605 Downward metaclass compatibility means that the metaclasses of a 
606 given class's anscestors are all either the same as (or a subclass 
607 of) that metaclass.
608
609 Here is a diagram showing a set of two classes (C<A> and C<B>) and 
610 two metaclasses (C<Meta::A> and C<Meta::B>) which have correct  
611 metaclass compatibility both upwards and downwards.
612
613     +---------+     +---------+
614     | Meta::A |<----| Meta::B |      <....... (instance of  )
615     +---------+     +---------+      <------- (inherits from)  
616          ^               ^
617          :               :
618     +---------+     +---------+
619     |    A    |<----|    B    |
620     +---------+     +---------+
621
622 As I said this is a highly esoteric topic and one you will only run 
623 into if you do a lot of subclassing of B<Class::MOP::Class>. If you 
624 are interested in why this is an issue see the paper 
625 I<Uniform and safe metaclass composition> linked to in the 
626 L<SEE ALSO> section of this document.
627
628 =head2 Using custom metaclasses
629
630 Always use the metaclass pragma when using a custom metaclass, this 
631 will ensure the proper initialization order and not accidentely 
632 create an incorrect type of metaclass for you. This is a very rare 
633 problem, and one which can only occur if you are doing deep metaclass 
634 programming. So in other words, don't worry about it.
635
636 =head1 PROTOCOLS
637
638 The protocol is divided into 3 main sub-protocols:
639
640 =over 4
641
642 =item The Class protocol
643
644 This provides a means of manipulating and introspecting a Perl 5 
645 class. It handles all of symbol table hacking for you, and provides 
646 a rich set of methods that go beyond simple package introspection.
647
648 See L<Class::MOP::Class> for more details.
649
650 =item The Attribute protocol
651
652 This provides a consistent represenation for an attribute of a 
653 Perl 5 class. Since there are so many ways to create and handle 
654 atttributes in Perl 5 OO, this attempts to provide as much of a 
655 unified approach as possible, while giving the freedom and 
656 flexibility to subclass for specialization.
657
658 See L<Class::MOP::Attribute> for more details.
659
660 =item The Method protocol
661
662 This provides a means of manipulating and introspecting methods in 
663 the Perl 5 object system. As with attributes, there are many ways to 
664 approach this topic, so we try to keep it pretty basic, while still 
665 making it possible to extend the system in many ways.
666
667 See L<Class::MOP::Method> for more details.
668
669 =back
670
671 =head1 FUNCTIONS
672
673 Class::MOP holds a cache of metaclasses, the following are functions 
674 (B<not methods>) which can be used to access that cache. It is not 
675 recommended that you mess with this, bad things could happen. But if 
676 you are brave and willing to risk it, go for it.
677
678 =over 4
679
680 =item B<get_all_metaclasses>
681
682 This will return an hash of all the metaclass instances that have 
683 been cached by B<Class::MOP::Class> keyed by the package name. 
684
685 =item B<get_all_metaclass_instances>
686
687 This will return an array of all the metaclass instances that have 
688 been cached by B<Class::MOP::Class>.
689
690 =item B<get_all_metaclass_names>
691
692 This will return an array of all the metaclass names that have 
693 been cached by B<Class::MOP::Class>.
694
695 =item B<get_metaclass_by_name ($name)>
696
697 =item B<store_metaclass_by_name ($name, $meta)>
698
699 =item B<weaken_metaclass ($name)>
700
701 =item B<does_metaclass_exist ($name)>
702
703 =item B<remove_metaclass_by_name ($name)>
704
705 =back
706
707 =head1 SEE ALSO
708
709 =head2 Books
710
711 There are very few books out on Meta Object Protocols and Metaclasses 
712 because it is such an esoteric topic. The following books are really 
713 the only ones I have found. If you know of any more, B<I<please>> 
714 email me and let me know, I would love to hear about them.
715
716 =over 4
717
718 =item "The Art of the Meta Object Protocol"
719
720 =item "Advances in Object-Oriented Metalevel Architecture and Reflection"
721
722 =item "Putting MetaClasses to Work"
723
724 =item "Smalltalk: The Language"
725
726 =back
727
728 =head2 Papers
729
730 =over 4
731
732 =item Uniform and safe metaclass composition
733
734 An excellent paper by the people who brought us the original Traits paper. 
735 This paper is on how Traits can be used to do safe metaclass composition, 
736 and offers an excellent introduction section which delves into the topic of 
737 metaclass compatibility.
738
739 L<http://www.iam.unibe.ch/~scg/Archive/Papers/Duca05ySafeMetaclassTrait.pdf>
740
741 =item Safe Metaclass Programming
742
743 This paper seems to precede the above paper, and propose a mix-in based 
744 approach as opposed to the Traits based approach. Both papers have similar 
745 information on the metaclass compatibility problem space. 
746
747 L<http://citeseer.ist.psu.edu/37617.html>
748
749 =back
750
751 =head2 Prior Art
752
753 =over 4
754
755 =item The Perl 6 MetaModel work in the Pugs project
756
757 =over 4
758
759 =item L<http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel>
760
761 =item L<http://svn.openfoundry.org/pugs/perl5/Perl6-ObjectSpace>
762
763 =back
764
765 =back
766
767 =head2 Article 
768
769 =over 4
770
771 =item CPAN Module Review of Class::MOP 
772
773 L<http://www.oreillynet.com/onlamp/blog/2006/06/cpan_module_review_classmop.html>
774
775 =back
776
777 =head1 SIMILAR MODULES
778
779 As I have said above, this module is a class-builder-builder, so it is 
780 not the same thing as modules like L<Class::Accessor> and 
781 L<Class::MethodMaker>. That being said there are very few modules on CPAN 
782 with similar goals to this module. The one I have found which is most 
783 like this module is L<Class::Meta>, although it's philosophy and the MOP it 
784 creates are very different from this modules. 
785
786 =head1 BUGS
787
788 All complex software has bugs lurking in it, and this module is no 
789 exception. If you find a bug please either email me, or add the bug
790 to cpan-RT.
791
792 =head1 CODE COVERAGE
793
794 I use L<Devel::Cover> to test the code coverage of my tests, below is the 
795 L<Devel::Cover> report on this module's test suite.
796
797  ---------------------------- ------ ------ ------ ------ ------ ------ ------
798  File                           stmt   bran   cond    sub    pod   time  total
799  ---------------------------- ------ ------ ------ ------ ------ ------ ------
800  Class/MOP.pm                   97.7  100.0   88.9   94.7  100.0    3.2   96.6
801  Class/MOP/Attribute.pm         75.5   77.9   82.4   88.3  100.0    4.0   81.5
802  Class/MOP/Class.pm             96.9   88.8   72.1   98.2  100.0   35.8   91.4
803  Class/MOP/Class/Immutable.pm   88.2   60.0    n/a   95.5  100.0    0.5   84.6
804  Class/MOP/Instance.pm          86.4   75.0   33.3   86.2  100.0    1.2   87.5
805  Class/MOP/Method.pm            97.5   75.0   61.5   80.6  100.0   12.7   89.7
806  Class/MOP/Module.pm           100.0    n/a   55.6  100.0  100.0    0.1   90.7
807  Class/MOP/Object.pm            73.3    n/a   20.0   80.0  100.0    0.1   66.7
808  Class/MOP/Package.pm           94.6   71.7   33.3  100.0  100.0   42.2   87.0
809  metaclass.pm                  100.0  100.0   83.3  100.0    n/a    0.2   97.7
810  ---------------------------- ------ ------ ------ ------ ------ ------ ------
811  Total                          91.3   80.4   69.8   91.9  100.0  100.0   88.1
812  ---------------------------- ------ ------ ------ ------ ------ ------ ------
813
814 =head1 ACKNOWLEDGEMENTS
815
816 =over 4
817
818 =item Rob Kinyon
819
820 Thanks to Rob for actually getting the development of this module kick-started. 
821
822 =back
823
824 =head1 AUTHORS
825
826 Stevan Little E<lt>stevan@iinteractive.comE<gt>
827
828 Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
829
830 =head1 COPYRIGHT AND LICENSE
831
832 Copyright 2006 by Infinity Interactive, Inc.
833
834 L<http://www.iinteractive.com>
835
836 This library is free software; you can redistribute it and/or modify
837 it under the same terms as Perl itself. 
838
839 =cut