tweaking a little here and there
[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.36';
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('$!metaclass' => (
442         init_arg => 'metaclass',
443     ))    
444 );
445
446 ## --------------------------------------------------------
447 ## Class::MOP::Instance
448
449 # NOTE:
450 # these don't yet do much of anything, but are just 
451 # included for completeness
452
453 Class::MOP::Instance->meta->add_attribute(
454     Class::MOP::Attribute->new('$!meta')
455 );
456
457 Class::MOP::Instance->meta->add_attribute(
458     Class::MOP::Attribute->new('@!slots')
459 );
460
461 ## --------------------------------------------------------
462 ## Now close all the Class::MOP::* classes
463
464 # NOTE:
465 # we don't need to inline the 
466 # constructors or the accessors 
467 # this only lengthens the compile 
468 # time of the MOP, and gives us 
469 # no actual benefits.
470
471 $_->meta->make_immutable(
472     inline_constructor => 0,
473     inline_accessors   => 0,
474 ) for qw/
475     Class::MOP::Package  
476     Class::MOP::Module   
477     Class::MOP::Class    
478     
479     Class::MOP::Attribute
480     Class::MOP::Method   
481     Class::MOP::Instance 
482     
483     Class::MOP::Object   
484
485     Class::MOP::Method::Accessor
486     Class::MOP::Method::Constructor    
487     Class::MOP::Method::Wrapped           
488 /;
489
490 1;
491
492 __END__
493
494 =pod
495
496 =head1 NAME 
497
498 Class::MOP - A Meta Object Protocol for Perl 5
499
500 =head1 SYNOPSIS
501
502   # ... This will come later, for now see
503   # the other SYNOPSIS for more information
504
505 =head1 DESCRIPTON
506
507 This module is an attempt to create a meta object protocol for the 
508 Perl 5 object system. It makes no attempt to change the behavior or 
509 characteristics of the Perl 5 object system, only to create a 
510 protocol for its manipulation and introspection.
511
512 That said, it does attempt to create the tools for building a rich 
513 set of extensions to the Perl 5 object system. Every attempt has been 
514 made for these tools to keep to the spirit of the Perl 5 object 
515 system that we all know and love.
516
517 This documentation is admittedly sparse on details, as time permits 
518 I will try to improve them. For now, I suggest looking at the items 
519 listed in the L<SEE ALSO> section for more information. In particular 
520 the book "The Art of the Meta Object Protocol" was very influential 
521 in the development of this system.
522
523 =head2 What is a Meta Object Protocol?
524
525 A meta object protocol is an API to an object system. 
526
527 To be more specific, it is a set of abstractions of the components of 
528 an object system (typically things like; classes, object, methods, 
529 object attributes, etc.). These abstractions can then be used to both 
530 inspect and manipulate the object system which they describe.
531
532 It can be said that there are two MOPs for any object system; the 
533 implicit MOP, and the explicit MOP. The implicit MOP handles things 
534 like method dispatch or inheritance, which happen automatically as 
535 part of how the object system works. The explicit MOP typically 
536 handles the introspection/reflection features of the object system. 
537 All object systems have implicit MOPs, without one, they would not 
538 work. Explict MOPs however as less common, and depending on the 
539 language can vary from restrictive (Reflection in Java or C#) to 
540 wide open (CLOS is a perfect example). 
541
542 =head2 Yet Another Class Builder!! Why?
543
544 This is B<not> a class builder so much as it is a I<class builder 
545 B<builder>>. My intent is that an end user does not use this module 
546 directly, but instead this module is used by module authors to 
547 build extensions and features onto the Perl 5 object system. 
548
549 =head2 Who is this module for?
550
551 This module is specifically for anyone who has ever created or 
552 wanted to create a module for the Class:: namespace. The tools which 
553 this module will provide will hopefully make it easier to do more 
554 complex things with Perl 5 classes by removing such barriers as 
555 the need to hack the symbol tables, or understand the fine details 
556 of method dispatch. 
557
558 =head2 What changes do I have to make to use this module?
559
560 This module was designed to be as unintrusive as possible. Many of 
561 its features are accessible without B<any> change to your existsing 
562 code at all. It is meant to be a compliment to your existing code and 
563 not an intrusion on your code base. Unlike many other B<Class::> 
564 modules, this module B<does not> require you subclass it, or even that 
565 you C<use> it in within your module's package. 
566
567 The only features which requires additions to your code are the 
568 attribute handling and instance construction features, and these are
569 both completely optional features. The only reason for this is because 
570 Perl 5's object system does not actually have these features built 
571 in. More information about this feature can be found below.
572
573 =head2 A Note about Performance?
574
575 It is a common misconception that explict MOPs are performance drains. 
576 But this is not a universal truth at all, it is an side-effect of 
577 specific implementations. For instance, using Java reflection is much 
578 slower because the JVM cannot take advantage of any compiler 
579 optimizations, and the JVM has to deal with much more runtime type 
580 information as well. Reflection in C# is marginally better as it was 
581 designed into the language and runtime (the CLR). In contrast, CLOS 
582 (the Common Lisp Object System) was built to support an explicit MOP, 
583 and so performance is tuned for it. 
584
585 This library in particular does it's absolute best to avoid putting 
586 B<any> drain at all upon your code's performance. In fact, by itself 
587 it does nothing to affect your existing code. So you only pay for 
588 what you actually use.
589
590 =head2 About Metaclass compatibility
591
592 This module makes sure that all metaclasses created are both upwards 
593 and downwards compatible. The topic of metaclass compatibility is 
594 highly esoteric and is something only encountered when doing deep and 
595 involved metaclass hacking. There are two basic kinds of metaclass 
596 incompatibility; upwards and downwards. 
597
598 Upwards metaclass compatibility means that the metaclass of a 
599 given class is either the same as (or a subclass of) all of the 
600 class's ancestors.
601
602 Downward metaclass compatibility means that the metaclasses of a 
603 given class's anscestors are all either the same as (or a subclass 
604 of) that metaclass.
605
606 Here is a diagram showing a set of two classes (C<A> and C<B>) and 
607 two metaclasses (C<Meta::A> and C<Meta::B>) which have correct  
608 metaclass compatibility both upwards and downwards.
609
610     +---------+     +---------+
611     | Meta::A |<----| Meta::B |      <....... (instance of  )
612     +---------+     +---------+      <------- (inherits from)  
613          ^               ^
614          :               :
615     +---------+     +---------+
616     |    A    |<----|    B    |
617     +---------+     +---------+
618
619 As I said this is a highly esoteric topic and one you will only run 
620 into if you do a lot of subclassing of B<Class::MOP::Class>. If you 
621 are interested in why this is an issue see the paper 
622 I<Uniform and safe metaclass composition> linked to in the 
623 L<SEE ALSO> section of this document.
624
625 =head2 Using custom metaclasses
626
627 Always use the metaclass pragma when using a custom metaclass, this 
628 will ensure the proper initialization order and not accidentely 
629 create an incorrect type of metaclass for you. This is a very rare 
630 problem, and one which can only occur if you are doing deep metaclass 
631 programming. So in other words, don't worry about it.
632
633 =head1 PROTOCOLS
634
635 The protocol is divided into 3 main sub-protocols:
636
637 =over 4
638
639 =item The Class protocol
640
641 This provides a means of manipulating and introspecting a Perl 5 
642 class. It handles all of symbol table hacking for you, and provides 
643 a rich set of methods that go beyond simple package introspection.
644
645 See L<Class::MOP::Class> for more details.
646
647 =item The Attribute protocol
648
649 This provides a consistent represenation for an attribute of a 
650 Perl 5 class. Since there are so many ways to create and handle 
651 atttributes in Perl 5 OO, this attempts to provide as much of a 
652 unified approach as possible, while giving the freedom and 
653 flexibility to subclass for specialization.
654
655 See L<Class::MOP::Attribute> for more details.
656
657 =item The Method protocol
658
659 This provides a means of manipulating and introspecting methods in 
660 the Perl 5 object system. As with attributes, there are many ways to 
661 approach this topic, so we try to keep it pretty basic, while still 
662 making it possible to extend the system in many ways.
663
664 See L<Class::MOP::Method> for more details.
665
666 =back
667
668 =head1 FUNCTIONS
669
670 Class::MOP holds a cache of metaclasses, the following are functions 
671 (B<not methods>) which can be used to access that cache. It is not 
672 recommended that you mess with this, bad things could happen. But if 
673 you are brave and willing to risk it, go for it.
674
675 =over 4
676
677 =item B<get_all_metaclasses>
678
679 This will return an hash of all the metaclass instances that have 
680 been cached by B<Class::MOP::Class> keyed by the package name. 
681
682 =item B<get_all_metaclass_instances>
683
684 This will return an array of all the metaclass instances that have 
685 been cached by B<Class::MOP::Class>.
686
687 =item B<get_all_metaclass_names>
688
689 This will return an array of all the metaclass names that have 
690 been cached by B<Class::MOP::Class>.
691
692 =item B<get_metaclass_by_name ($name)>
693
694 =item B<store_metaclass_by_name ($name, $meta)>
695
696 =item B<weaken_metaclass ($name)>
697
698 =item B<does_metaclass_exist ($name)>
699
700 =item B<remove_metaclass_by_name ($name)>
701
702 =back
703
704 =head1 SEE ALSO
705
706 =head2 Books
707
708 There are very few books out on Meta Object Protocols and Metaclasses 
709 because it is such an esoteric topic. The following books are really 
710 the only ones I have found. If you know of any more, B<I<please>> 
711 email me and let me know, I would love to hear about them.
712
713 =over 4
714
715 =item "The Art of the Meta Object Protocol"
716
717 =item "Advances in Object-Oriented Metalevel Architecture and Reflection"
718
719 =item "Putting MetaClasses to Work"
720
721 =item "Smalltalk: The Language"
722
723 =back
724
725 =head2 Papers
726
727 =over 4
728
729 =item Uniform and safe metaclass composition
730
731 An excellent paper by the people who brought us the original Traits paper. 
732 This paper is on how Traits can be used to do safe metaclass composition, 
733 and offers an excellent introduction section which delves into the topic of 
734 metaclass compatibility.
735
736 L<http://www.iam.unibe.ch/~scg/Archive/Papers/Duca05ySafeMetaclassTrait.pdf>
737
738 =item Safe Metaclass Programming
739
740 This paper seems to precede the above paper, and propose a mix-in based 
741 approach as opposed to the Traits based approach. Both papers have similar 
742 information on the metaclass compatibility problem space. 
743
744 L<http://citeseer.ist.psu.edu/37617.html>
745
746 =back
747
748 =head2 Prior Art
749
750 =over 4
751
752 =item The Perl 6 MetaModel work in the Pugs project
753
754 =over 4
755
756 =item L<http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel>
757
758 =item L<http://svn.openfoundry.org/pugs/perl5/Perl6-ObjectSpace>
759
760 =back
761
762 =back
763
764 =head2 Article 
765
766 =over 4
767
768 =item CPAN Module Review of Class::MOP 
769
770 L<http://www.oreillynet.com/onlamp/blog/2006/06/cpan_module_review_classmop.html>
771
772 =back
773
774 =head1 SIMILAR MODULES
775
776 As I have said above, this module is a class-builder-builder, so it is 
777 not the same thing as modules like L<Class::Accessor> and 
778 L<Class::MethodMaker>. That being said there are very few modules on CPAN 
779 with similar goals to this module. The one I have found which is most 
780 like this module is L<Class::Meta>, although it's philosophy and the MOP it 
781 creates are very different from this modules. 
782
783 =head1 BUGS
784
785 All complex software has bugs lurking in it, and this module is no 
786 exception. If you find a bug please either email me, or add the bug
787 to cpan-RT.
788
789 =head1 CODE COVERAGE
790
791 I use L<Devel::Cover> to test the code coverage of my tests, below is the 
792 L<Devel::Cover> report on this module's test suite.
793
794  ---------------------------- ------ ------ ------ ------ ------ ------ ------
795  File                           stmt   bran   cond    sub    pod   time  total
796  ---------------------------- ------ ------ ------ ------ ------ ------ ------
797  Class/MOP.pm                   97.7  100.0   88.9   94.7  100.0    3.2   96.6
798  Class/MOP/Attribute.pm         75.5   77.9   82.4   88.3  100.0    4.0   81.5
799  Class/MOP/Class.pm             96.9   88.8   72.1   98.2  100.0   35.8   91.4
800  Class/MOP/Class/Immutable.pm   88.2   60.0    n/a   95.5  100.0    0.5   84.6
801  Class/MOP/Instance.pm          86.4   75.0   33.3   86.2  100.0    1.2   87.5
802  Class/MOP/Method.pm            97.5   75.0   61.5   80.6  100.0   12.7   89.7
803  Class/MOP/Module.pm           100.0    n/a   55.6  100.0  100.0    0.1   90.7
804  Class/MOP/Object.pm            73.3    n/a   20.0   80.0  100.0    0.1   66.7
805  Class/MOP/Package.pm           94.6   71.7   33.3  100.0  100.0   42.2   87.0
806  metaclass.pm                  100.0  100.0   83.3  100.0    n/a    0.2   97.7
807  ---------------------------- ------ ------ ------ ------ ------ ------ ------
808  Total                          91.3   80.4   69.8   91.9  100.0  100.0   88.1
809  ---------------------------- ------ ------ ------ ------ ------ ------ ------
810
811 =head1 ACKNOWLEDGEMENTS
812
813 =over 4
814
815 =item Rob Kinyon
816
817 Thanks to Rob for actually getting the development of this module kick-started. 
818
819 =back
820
821 =head1 AUTHORS
822
823 Stevan Little E<lt>stevan@iinteractive.comE<gt>
824
825 Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
826
827 =head1 COPYRIGHT AND LICENSE
828
829 Copyright 2006 by Infinity Interactive, Inc.
830
831 L<http://www.iinteractive.com>
832
833 This library is free software; you can redistribute it and/or modify
834 it under the same terms as Perl itself. 
835
836 =cut