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