Bump the version on Class::MOP so I can run Moose's Makefile.PL
[gitmo/Class-MOP.git] / lib / Class / MOP.pm
1
2 package Class::MOP;
3
4 use strict;
5 use warnings;
6
7 use MRO::Compat;
8
9 use Carp         'confess';
10 use Scalar::Util 'weaken';
11
12 use Class::MOP::Class;
13 use Class::MOP::Attribute;
14 use Class::MOP::Method;
15
16 use Class::MOP::Immutable;
17
18 BEGIN {
19     our $VERSION   = '0.56';
20     our $AUTHORITY = 'cpan:STEVAN';    
21     
22     use XSLoader;
23     XSLoader::load( 'Class::MOP', $VERSION );    
24     
25     unless ($] < 5.009_005) {
26         require mro;
27         no warnings 'redefine', 'prototype';
28         *check_package_cache_flag = \&mro::get_pkg_gen;
29         *IS_RUNNING_ON_5_10 = sub () { 1 };
30     }
31     else {
32         *IS_RUNNING_ON_5_10 = sub () { 0 };        
33     }
34 }
35
36 {
37     # Metaclasses are singletons, so we cache them here.
38     # there is no need to worry about destruction though
39     # because they should die only when the program dies.
40     # After all, do package definitions even get reaped?
41     my %METAS;
42
43     # means of accessing all the metaclasses that have
44     # been initialized thus far (for mugwumps obj browser)
45     sub get_all_metaclasses         {        %METAS         }
46     sub get_all_metaclass_instances { values %METAS         }
47     sub get_all_metaclass_names     { keys   %METAS         }
48     sub get_metaclass_by_name       { $METAS{$_[0]}         }
49     sub store_metaclass_by_name     { $METAS{$_[0]} = $_[1] }
50     sub weaken_metaclass            { weaken($METAS{$_[0]}) }
51     sub does_metaclass_exist        { exists $METAS{$_[0]} && defined $METAS{$_[0]} }
52     sub remove_metaclass_by_name    { $METAS{$_[0]} = undef }
53
54     # NOTE:
55     # We only cache metaclasses, meaning instances of
56     # Class::MOP::Class. We do not cache instance of
57     # Class::MOP::Package or Class::MOP::Module. Mostly
58     # because I don't yet see a good reason to do so.
59 }
60
61 sub load_class {
62     my $class = shift;
63     # see if this is already
64     # loaded in the symbol table
65     return 1 if is_class_loaded($class);
66     # otherwise require it ...
67     my $file = $class . '.pm';
68     $file =~ s{::}{/}g;
69     eval { CORE::require($file) };
70     confess "Could not load class ($class) because : $@" if $@;
71     unless (does_metaclass_exist($class)) {
72         eval { Class::MOP::Class->initialize($class) };
73         confess "Could not initialize class ($class) because : $@" if $@;
74     }
75     1; # return true if it worked
76 }
77
78 sub is_class_loaded {
79     my $class = shift;
80     no strict 'refs';
81     return 1 if defined ${"${class}::VERSION"} || defined @{"${class}::ISA"};
82     foreach my $symbol (keys %{"${class}::"}) {
83             next if substr($symbol, -2, 2) eq '::';
84             return 1 if defined &{"${class}::${symbol}"};
85     }
86     return 0;
87 }
88
89
90 ## ----------------------------------------------------------------------------
91 ## Setting up our environment ...
92 ## ----------------------------------------------------------------------------
93 ## Class::MOP needs to have a few things in the global perl environment so
94 ## that it can operate effectively. Those things are done here.
95 ## ----------------------------------------------------------------------------
96
97 # ... nothing yet actually ;)
98
99 ## ----------------------------------------------------------------------------
100 ## Bootstrapping
101 ## ----------------------------------------------------------------------------
102 ## The code below here is to bootstrap our MOP with itself. This is also
103 ## sometimes called "tying the knot". By doing this, we make it much easier
104 ## to extend the MOP through subclassing and such since now you can use the
105 ## MOP itself to extend itself.
106 ##
107 ## Yes, I know, thats weird and insane, but it's a good thing, trust me :)
108 ## ----------------------------------------------------------------------------
109
110 # We need to add in the meta-attributes here so that
111 # any subclass of Class::MOP::* will be able to
112 # inherit them using &construct_instance
113
114 ## --------------------------------------------------------
115 ## Class::MOP::Package
116
117 Class::MOP::Package->meta->add_attribute(
118     Class::MOP::Attribute->new('$!package' => (
119         reader   => {
120             # NOTE: we need to do this in order
121             # for the instance meta-object to
122             # not fall into meta-circular death
123             #
124             # we just alias the original method
125             # rather than re-produce it here
126             'name' => \&Class::MOP::Package::name
127         },
128         init_arg => 'package',
129     ))
130 );
131
132 Class::MOP::Package->meta->add_attribute(
133     Class::MOP::Attribute->new('%!namespace' => (
134         reader => {
135             # NOTE:
136             # we just alias the original method
137             # rather than re-produce it here
138             'namespace' => \&Class::MOP::Package::namespace
139         },
140         init_arg => undef,
141         default  => sub { \undef }
142     ))
143 );
144
145 # NOTE:
146 # use the metaclass to construct the meta-package
147 # which is a superclass of the metaclass itself :P
148 Class::MOP::Package->meta->add_method('initialize' => sub {
149     my $class        = shift;
150     my $package_name = shift;
151     $class->meta->new_object('package' => $package_name, @_);
152 });
153
154 ## --------------------------------------------------------
155 ## Class::MOP::Module
156
157 # NOTE:
158 # yeah this is kind of stretching things a bit,
159 # but truthfully the version should be an attribute
160 # of the Module, the weirdness comes from having to
161 # stick to Perl 5 convention and store it in the
162 # $VERSION package variable. Basically if you just
163 # squint at it, it will look how you want it to look.
164 # Either as a package variable, or as a attribute of
165 # the metaclass, isn't abstraction great :)
166
167 Class::MOP::Module->meta->add_attribute(
168     Class::MOP::Attribute->new('$!version' => (
169         reader => {
170             # NOTE:
171             # we just alias the original method
172             # rather than re-produce it here
173             'version' => \&Class::MOP::Module::version
174         },
175         init_arg => undef,
176         default  => sub { \undef }
177     ))
178 );
179
180 # NOTE:
181 # By following the same conventions as version here,
182 # we are opening up the possibility that people can
183 # use the $AUTHORITY in non-Class::MOP modules as
184 # well.
185
186 Class::MOP::Module->meta->add_attribute(
187     Class::MOP::Attribute->new('$!authority' => (
188         reader => {
189             # NOTE:
190             # we just alias the original method
191             # rather than re-produce it here
192             'authority' => \&Class::MOP::Module::authority
193         },
194         init_arg => undef,
195         default  => sub { \undef }
196     ))
197 );
198
199 ## --------------------------------------------------------
200 ## Class::MOP::Class
201
202 Class::MOP::Class->meta->add_attribute(
203     Class::MOP::Attribute->new('%!attributes' => (
204         reader   => {
205             # NOTE: we need to do this in order
206             # for the instance meta-object to
207             # not fall into meta-circular death
208             #
209             # we just alias the original method
210             # rather than re-produce it here
211             'get_attribute_map' => \&Class::MOP::Class::get_attribute_map
212         },
213         init_arg => 'attributes',
214         default  => sub { {} }
215     ))
216 );
217
218 Class::MOP::Class->meta->add_attribute(
219     Class::MOP::Attribute->new('%!methods' => (
220         init_arg => 'methods',
221         reader   => {
222             # NOTE:
223             # we just alias the original method
224             # rather than re-produce it here
225             'get_method_map' => \&Class::MOP::Class::get_method_map
226         },
227         default => sub { {} }
228     ))
229 );
230
231 Class::MOP::Class->meta->add_attribute(
232     Class::MOP::Attribute->new('@!superclasses' => (
233         accessor => {
234             # NOTE:
235             # we just alias the original method
236             # rather than re-produce it here
237             'superclasses' => \&Class::MOP::Class::superclasses
238         },
239         init_arg => undef,
240         default  => sub { \undef }
241     ))
242 );
243
244 Class::MOP::Class->meta->add_attribute(
245     Class::MOP::Attribute->new('$!attribute_metaclass' => (
246         reader   => {
247             # NOTE:
248             # we just alias the original method
249             # rather than re-produce it here
250             'attribute_metaclass' => \&Class::MOP::Class::attribute_metaclass
251         },
252         init_arg => 'attribute_metaclass',
253         default  => 'Class::MOP::Attribute',
254     ))
255 );
256
257 Class::MOP::Class->meta->add_attribute(
258     Class::MOP::Attribute->new('$!method_metaclass' => (
259         reader   => {
260             # NOTE:
261             # we just alias the original method
262             # rather than re-produce it here
263             'method_metaclass' => \&Class::MOP::Class::method_metaclass
264         },
265         init_arg => 'method_metaclass',
266         default  => 'Class::MOP::Method',
267     ))
268 );
269
270 Class::MOP::Class->meta->add_attribute(
271     Class::MOP::Attribute->new('$!instance_metaclass' => (
272         reader   => {
273             # NOTE: we need to do this in order
274             # for the instance meta-object to
275             # not fall into meta-circular death
276             #
277             # we just alias the original method
278             # rather than re-produce it here
279             'instance_metaclass' => \&Class::MOP::Class::instance_metaclass
280         },
281         init_arg => 'instance_metaclass',
282         default  => 'Class::MOP::Instance',
283     ))
284 );
285
286 # NOTE:
287 # we don't actually need to tie the knot with
288 # Class::MOP::Class here, it is actually handled
289 # within Class::MOP::Class itself in the
290 # construct_class_instance method.
291
292 ## --------------------------------------------------------
293 ## Class::MOP::Attribute
294
295 Class::MOP::Attribute->meta->add_attribute(
296     Class::MOP::Attribute->new('$!name' => (
297         init_arg => 'name',
298         reader   => {
299             # NOTE: we need to do this in order
300             # for the instance meta-object to
301             # not fall into meta-circular death
302             #
303             # we just alias the original method
304             # rather than re-produce it here
305             'name' => \&Class::MOP::Attribute::name
306         }
307     ))
308 );
309
310 Class::MOP::Attribute->meta->add_attribute(
311     Class::MOP::Attribute->new('$!associated_class' => (
312         init_arg => 'associated_class',
313         reader   => {
314             # NOTE: we need to do this in order
315             # for the instance meta-object to
316             # not fall into meta-circular death
317             #
318             # we just alias the original method
319             # rather than re-produce it here
320             'associated_class' => \&Class::MOP::Attribute::associated_class
321         }
322     ))
323 );
324
325 Class::MOP::Attribute->meta->add_attribute(
326     Class::MOP::Attribute->new('$!accessor' => (
327         init_arg  => 'accessor',
328         reader    => { 'accessor'     => \&Class::MOP::Attribute::accessor     },
329         predicate => { 'has_accessor' => \&Class::MOP::Attribute::has_accessor },
330     ))
331 );
332
333 Class::MOP::Attribute->meta->add_attribute(
334     Class::MOP::Attribute->new('$!reader' => (
335         init_arg  => 'reader',
336         reader    => { 'reader'     => \&Class::MOP::Attribute::reader     },
337         predicate => { 'has_reader' => \&Class::MOP::Attribute::has_reader },
338     ))
339 );
340
341 Class::MOP::Attribute->meta->add_attribute(
342     Class::MOP::Attribute->new('$!initializer' => (
343         init_arg  => 'initializer',
344         reader    => { 'initializer'     => \&Class::MOP::Attribute::initializer     },
345         predicate => { 'has_initializer' => \&Class::MOP::Attribute::has_initializer },
346     ))
347 );
348
349 Class::MOP::Attribute->meta->add_attribute(
350     Class::MOP::Attribute->new('$!writer' => (
351         init_arg  => 'writer',
352         reader    => { 'writer'     => \&Class::MOP::Attribute::writer     },
353         predicate => { 'has_writer' => \&Class::MOP::Attribute::has_writer },
354     ))
355 );
356
357 Class::MOP::Attribute->meta->add_attribute(
358     Class::MOP::Attribute->new('$!predicate' => (
359         init_arg  => 'predicate',
360         reader    => { 'predicate'     => \&Class::MOP::Attribute::predicate     },
361         predicate => { 'has_predicate' => \&Class::MOP::Attribute::has_predicate },
362     ))
363 );
364
365 Class::MOP::Attribute->meta->add_attribute(
366     Class::MOP::Attribute->new('$!clearer' => (
367         init_arg  => 'clearer',
368         reader    => { 'clearer'     => \&Class::MOP::Attribute::clearer     },
369         predicate => { 'has_clearer' => \&Class::MOP::Attribute::has_clearer },
370     ))
371 );
372
373 Class::MOP::Attribute->meta->add_attribute(
374     Class::MOP::Attribute->new('$!builder' => (
375         init_arg  => 'builder',
376         reader    => { 'builder'     => \&Class::MOP::Attribute::builder     },
377         predicate => { 'has_builder' => \&Class::MOP::Attribute::has_builder },
378     ))
379 );
380
381 Class::MOP::Attribute->meta->add_attribute(
382     Class::MOP::Attribute->new('$!init_arg' => (
383         init_arg  => 'init_arg',
384         reader    => { 'init_arg'     => \&Class::MOP::Attribute::init_arg     },
385         predicate => { 'has_init_arg' => \&Class::MOP::Attribute::has_init_arg },
386     ))
387 );
388
389 Class::MOP::Attribute->meta->add_attribute(
390     Class::MOP::Attribute->new('$!default' => (
391         init_arg  => 'default',
392         # default has a custom 'reader' method ...
393         predicate => { 'has_default' => \&Class::MOP::Attribute::has_default },
394     ))
395 );
396
397 Class::MOP::Attribute->meta->add_attribute(
398     Class::MOP::Attribute->new('@!associated_methods' => (
399         init_arg => 'associated_methods',
400         reader   => { 'associated_methods' => \&Class::MOP::Attribute::associated_methods },
401         default  => sub { [] }
402     ))
403 );
404
405 # NOTE: (meta-circularity)
406 # This should be one of the last things done
407 # it will "tie the knot" with Class::MOP::Attribute
408 # so that it uses the attributes meta-objects
409 # to construct itself.
410 Class::MOP::Attribute->meta->add_method('new' => sub {
411     my $class   = shift;
412     my $name    = shift;
413     my %options = @_;
414
415     (defined $name && $name)
416         || confess "You must provide a name for the attribute";
417     $options{init_arg} = $name
418         if not exists $options{init_arg};
419
420     if(exists $options{builder}){
421         confess("builder must be a defined scalar value which is a method name")
422             if ref $options{builder} || !(defined $options{builder});
423         confess("Setting both default and builder is not allowed.")
424             if exists $options{default};
425     } else {
426         (Class::MOP::Attribute::is_default_a_coderef(\%options))
427             || confess("References are not allowed as default values, you must ".
428                        "wrap then in a CODE reference (ex: sub { [] } and not [])")
429                 if exists $options{default} && ref $options{default};
430     }
431     # return the new object
432     $class->meta->new_object(name => $name, %options);
433 });
434
435 Class::MOP::Attribute->meta->add_method('clone' => sub {
436     my $self  = shift;
437     $self->meta->clone_object($self, @_);
438 });
439
440 ## --------------------------------------------------------
441 ## Class::MOP::Method
442
443 Class::MOP::Method->meta->add_attribute(
444     Class::MOP::Attribute->new('&!body' => (
445         init_arg => 'body',
446         reader   => { 'body' => \&Class::MOP::Method::body },
447     ))
448 );
449
450 ## --------------------------------------------------------
451 ## Class::MOP::Method::Wrapped
452
453 # NOTE:
454 # the way this item is initialized, this
455 # really does not follow the standard
456 # practices of attributes, but we put
457 # it here for completeness
458 Class::MOP::Method::Wrapped->meta->add_attribute(
459     Class::MOP::Attribute->new('%!modifier_table')
460 );
461
462 ## --------------------------------------------------------
463 ## Class::MOP::Method::Generated
464
465 Class::MOP::Method::Generated->meta->add_attribute(
466     Class::MOP::Attribute->new('$!is_inline' => (
467         init_arg => 'is_inline',
468         reader   => { 'is_inline' => \&Class::MOP::Method::Generated::is_inline },
469     ))
470 );
471
472 ## --------------------------------------------------------
473 ## Class::MOP::Method::Accessor
474
475 Class::MOP::Method::Accessor->meta->add_attribute(
476     Class::MOP::Attribute->new('$!attribute' => (
477         init_arg => 'attribute',
478         reader   => {
479             'associated_attribute' => \&Class::MOP::Method::Accessor::associated_attribute
480         },
481     ))
482 );
483
484 Class::MOP::Method::Accessor->meta->add_attribute(
485     Class::MOP::Attribute->new('$!accessor_type' => (
486         init_arg => 'accessor_type',
487         reader   => { 'accessor_type' => \&Class::MOP::Method::Accessor::accessor_type },
488     ))
489 );
490
491
492 ## --------------------------------------------------------
493 ## Class::MOP::Method::Constructor
494
495 Class::MOP::Method::Constructor->meta->add_attribute(
496     Class::MOP::Attribute->new('%!options' => (
497         init_arg => 'options',
498         reader   => {
499             'options' => \&Class::MOP::Method::Constructor::options
500         },
501     ))
502 );
503
504 Class::MOP::Method::Constructor->meta->add_attribute(
505     Class::MOP::Attribute->new('$!associated_metaclass' => (
506         init_arg => 'metaclass',
507         reader   => {
508             'associated_metaclass' => \&Class::MOP::Method::Constructor::associated_metaclass
509         },
510     ))
511 );
512
513 ## --------------------------------------------------------
514 ## Class::MOP::Instance
515
516 # NOTE:
517 # these don't yet do much of anything, but are just
518 # included for completeness
519
520 Class::MOP::Instance->meta->add_attribute(
521     Class::MOP::Attribute->new('$!meta')
522 );
523
524 Class::MOP::Instance->meta->add_attribute(
525     Class::MOP::Attribute->new('@!slots')
526 );
527
528 ## --------------------------------------------------------
529 ## Now close all the Class::MOP::* classes
530
531 # NOTE:
532 # we don't need to inline the
533 # constructors or the accessors
534 # this only lengthens the compile
535 # time of the MOP, and gives us
536 # no actual benefits.
537
538 $_->meta->make_immutable(
539     inline_constructor => 0,
540     inline_accessors   => 0,
541 ) for qw/
542     Class::MOP::Package
543     Class::MOP::Module
544     Class::MOP::Class
545
546     Class::MOP::Attribute
547     Class::MOP::Method
548     Class::MOP::Instance
549
550     Class::MOP::Object
551
552     Class::MOP::Method::Generated
553
554     Class::MOP::Method::Accessor
555     Class::MOP::Method::Constructor
556     Class::MOP::Method::Wrapped
557 /;
558
559 1;
560
561 __END__
562
563 =pod
564
565 =head1 NAME
566
567 Class::MOP - A Meta Object Protocol for Perl 5
568
569 =head1 DESCRIPTON
570
571 This module is a fully functioning meta object protocol for the
572 Perl 5 object system. It makes no attempt to change the behavior or
573 characteristics of the Perl 5 object system, only to create a
574 protocol for its manipulation and introspection.
575
576 That said, it does attempt to create the tools for building a rich
577 set of extensions to the Perl 5 object system. Every attempt has been
578 made for these tools to keep to the spirit of the Perl 5 object
579 system that we all know and love.
580
581 This documentation is admittedly sparse on details, as time permits
582 I will try to improve them. For now, I suggest looking at the items
583 listed in the L<SEE ALSO> section for more information. In particular
584 the book "The Art of the Meta Object Protocol" was very influential
585 in the development of this system.
586
587 =head2 What is a Meta Object Protocol?
588
589 A meta object protocol is an API to an object system.
590
591 To be more specific, it is a set of abstractions of the components of
592 an object system (typically things like; classes, object, methods,
593 object attributes, etc.). These abstractions can then be used to both
594 inspect and manipulate the object system which they describe.
595
596 It can be said that there are two MOPs for any object system; the
597 implicit MOP, and the explicit MOP. The implicit MOP handles things
598 like method dispatch or inheritance, which happen automatically as
599 part of how the object system works. The explicit MOP typically
600 handles the introspection/reflection features of the object system.
601 All object systems have implicit MOPs, without one, they would not
602 work. Explict MOPs however as less common, and depending on the
603 language can vary from restrictive (Reflection in Java or C#) to
604 wide open (CLOS is a perfect example).
605
606 =head2 Yet Another Class Builder!! Why?
607
608 This is B<not> a class builder so much as it is a I<class builder
609 B<builder>>. My intent is that an end user does not use this module
610 directly, but instead this module is used by module authors to
611 build extensions and features onto the Perl 5 object system.
612
613 =head2 Who is this module for?
614
615 This module is specifically for anyone who has ever created or
616 wanted to create a module for the Class:: namespace. The tools which
617 this module will provide will hopefully make it easier to do more
618 complex things with Perl 5 classes by removing such barriers as
619 the need to hack the symbol tables, or understand the fine details
620 of method dispatch.
621
622 =head2 What changes do I have to make to use this module?
623
624 This module was designed to be as unintrusive as possible. Many of
625 its features are accessible without B<any> change to your existsing
626 code at all. It is meant to be a compliment to your existing code and
627 not an intrusion on your code base. Unlike many other B<Class::>
628 modules, this module B<does not> require you subclass it, or even that
629 you C<use> it in within your module's package.
630
631 The only features which requires additions to your code are the
632 attribute handling and instance construction features, and these are
633 both completely optional features. The only reason for this is because
634 Perl 5's object system does not actually have these features built
635 in. More information about this feature can be found below.
636
637 =head2 A Note about Performance?
638
639 It is a common misconception that explict MOPs are performance drains.
640 But this is not a universal truth at all, it is an side-effect of
641 specific implementations. For instance, using Java reflection is much
642 slower because the JVM cannot take advantage of any compiler
643 optimizations, and the JVM has to deal with much more runtime type
644 information as well. Reflection in C# is marginally better as it was
645 designed into the language and runtime (the CLR). In contrast, CLOS
646 (the Common Lisp Object System) was built to support an explicit MOP,
647 and so performance is tuned for it.
648
649 This library in particular does it's absolute best to avoid putting
650 B<any> drain at all upon your code's performance. In fact, by itself
651 it does nothing to affect your existing code. So you only pay for
652 what you actually use.
653
654 =head2 About Metaclass compatibility
655
656 This module makes sure that all metaclasses created are both upwards
657 and downwards compatible. The topic of metaclass compatibility is
658 highly esoteric and is something only encountered when doing deep and
659 involved metaclass hacking. There are two basic kinds of metaclass
660 incompatibility; upwards and downwards.
661
662 Upwards metaclass compatibility means that the metaclass of a
663 given class is either the same as (or a subclass of) all of the
664 class's ancestors.
665
666 Downward metaclass compatibility means that the metaclasses of a
667 given class's anscestors are all either the same as (or a subclass
668 of) that metaclass.
669
670 Here is a diagram showing a set of two classes (C<A> and C<B>) and
671 two metaclasses (C<Meta::A> and C<Meta::B>) which have correct
672 metaclass compatibility both upwards and downwards.
673
674     +---------+     +---------+
675     | Meta::A |<----| Meta::B |      <....... (instance of  )
676     +---------+     +---------+      <------- (inherits from)
677          ^               ^
678          :               :
679     +---------+     +---------+
680     |    A    |<----|    B    |
681     +---------+     +---------+
682
683 As I said this is a highly esoteric topic and one you will only run
684 into if you do a lot of subclassing of B<Class::MOP::Class>. If you
685 are interested in why this is an issue see the paper
686 I<Uniform and safe metaclass composition> linked to in the
687 L<SEE ALSO> section of this document.
688
689 =head2 Using custom metaclasses
690
691 Always use the metaclass pragma when using a custom metaclass, this
692 will ensure the proper initialization order and not accidentely
693 create an incorrect type of metaclass for you. This is a very rare
694 problem, and one which can only occur if you are doing deep metaclass
695 programming. So in other words, don't worry about it.
696
697 =head1 PROTOCOLS
698
699 The protocol is divided into 4 main sub-protocols:
700
701 =over 4
702
703 =item The Class protocol
704
705 This provides a means of manipulating and introspecting a Perl 5
706 class. It handles all of symbol table hacking for you, and provides
707 a rich set of methods that go beyond simple package introspection.
708
709 See L<Class::MOP::Class> for more details.
710
711 =item The Attribute protocol
712
713 This provides a consistent represenation for an attribute of a
714 Perl 5 class. Since there are so many ways to create and handle
715 attributes in Perl 5 OO, this attempts to provide as much of a
716 unified approach as possible, while giving the freedom and
717 flexibility to subclass for specialization.
718
719 See L<Class::MOP::Attribute> for more details.
720
721 =item The Method protocol
722
723 This provides a means of manipulating and introspecting methods in
724 the Perl 5 object system. As with attributes, there are many ways to
725 approach this topic, so we try to keep it pretty basic, while still
726 making it possible to extend the system in many ways.
727
728 See L<Class::MOP::Method> for more details.
729
730 =item The Instance protocol
731
732 This provides a layer of abstraction for creating object instances. 
733 Since the other layers use this protocol, it is relatively easy to 
734 change the type of your instances from the default HASH ref to other
735 types of references. Several examples are provided in the F<examples/> 
736 directory included in this distribution.
737
738 See L<Class::MOP::Instance> for more details.
739
740 =back
741
742 =head1 FUNCTIONS
743
744 =head2 Constants
745
746 =over 4
747
748 =item I<IS_RUNNING_ON_5_10>
749
750 We set this constant depending on what version perl we are on, this 
751 allows us to take advantage of new 5.10 features and stay backwards 
752 compat.
753
754 =back
755
756 =head2 Utility functions
757
758 =over 4
759
760 =item B<load_class ($class_name)>
761
762 This will load a given C<$class_name> and if it does not have an
763 already initialized metaclass, then it will intialize one for it.
764 This function can be used in place of tricks like 
765 C<eval "use $module"> or using C<require>.
766
767 =item B<is_class_loaded ($class_name)>
768
769 This will return a boolean depending on if the C<$class_name> has
770 been loaded.
771
772 NOTE: This does a basic check of the symbol table to try and
773 determine as best it can if the C<$class_name> is loaded, it
774 is probably correct about 99% of the time.
775
776 =item B<check_package_cache_flag ($pkg)>
777
778 This will return an integer that is managed by C<Class::MOP::Class>
779 to determine if a module's symbol table has been altered. 
780
781 In Perl 5.10 or greater, this flag is package specific. However in 
782 versions prior to 5.10, this will use the C<PL_sub_generation> variable
783 which is not package specific. 
784
785 =item B<get_code_info ($code)>
786
787 This function returns two values, the name of the package the C<$code> 
788 is from and the name of the C<$code> itself. This is used by several 
789 elements of the MOP to detemine where a given C<$code> reference is from.
790
791 =back
792
793 =head2 Metaclass cache functions
794
795 Class::MOP holds a cache of metaclasses, the following are functions
796 (B<not methods>) which can be used to access that cache. It is not
797 recommended that you mess with this, bad things could happen. But if
798 you are brave and willing to risk it, go for it.
799
800 =over 4
801
802 =item B<get_all_metaclasses>
803
804 This will return an hash of all the metaclass instances that have
805 been cached by B<Class::MOP::Class> keyed by the package name.
806
807 =item B<get_all_metaclass_instances>
808
809 This will return an array of all the metaclass instances that have
810 been cached by B<Class::MOP::Class>.
811
812 =item B<get_all_metaclass_names>
813
814 This will return an array of all the metaclass names that have
815 been cached by B<Class::MOP::Class>.
816
817 =item B<get_metaclass_by_name ($name)>
818
819 This will return a cached B<Class::MOP::Class> instance of nothing
820 if no metaclass exist by that C<$name>.
821
822 =item B<store_metaclass_by_name ($name, $meta)>
823
824 This will store a metaclass in the cache at the supplied C<$key>.
825
826 =item B<weaken_metaclass ($name)>
827
828 In rare cases it is desireable to store a weakened reference in 
829 the metaclass cache. This function will weaken the reference to 
830 the metaclass stored in C<$name>.
831
832 =item B<does_metaclass_exist ($name)>
833
834 This will return true of there exists a metaclass stored in the 
835 C<$name> key and return false otherwise.
836
837 =item B<remove_metaclass_by_name ($name)>
838
839 This will remove a the metaclass stored in the C<$name> key.
840
841 =back
842
843 =head1 SEE ALSO
844
845 =head2 Books
846
847 There are very few books out on Meta Object Protocols and Metaclasses
848 because it is such an esoteric topic. The following books are really
849 the only ones I have found. If you know of any more, B<I<please>>
850 email me and let me know, I would love to hear about them.
851
852 =over 4
853
854 =item "The Art of the Meta Object Protocol"
855
856 =item "Advances in Object-Oriented Metalevel Architecture and Reflection"
857
858 =item "Putting MetaClasses to Work"
859
860 =item "Smalltalk: The Language"
861
862 =back
863
864 =head2 Papers
865
866 =over 4
867
868 =item Uniform and safe metaclass composition
869
870 An excellent paper by the people who brought us the original Traits paper.
871 This paper is on how Traits can be used to do safe metaclass composition,
872 and offers an excellent introduction section which delves into the topic of
873 metaclass compatibility.
874
875 L<http://www.iam.unibe.ch/~scg/Archive/Papers/Duca05ySafeMetaclassTrait.pdf>
876
877 =item Safe Metaclass Programming
878
879 This paper seems to precede the above paper, and propose a mix-in based
880 approach as opposed to the Traits based approach. Both papers have similar
881 information on the metaclass compatibility problem space.
882
883 L<http://citeseer.ist.psu.edu/37617.html>
884
885 =back
886
887 =head2 Prior Art
888
889 =over 4
890
891 =item The Perl 6 MetaModel work in the Pugs project
892
893 =over 4
894
895 =item L<http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel>
896
897 =item L<http://svn.openfoundry.org/pugs/perl5/Perl6-ObjectSpace>
898
899 =back
900
901 =back
902
903 =head2 Articles
904
905 =over 4
906
907 =item CPAN Module Review of Class::MOP
908
909 L<http://www.oreillynet.com/onlamp/blog/2006/06/cpan_module_review_classmop.html>
910
911 =back
912
913 =head1 SIMILAR MODULES
914
915 As I have said above, this module is a class-builder-builder, so it is
916 not the same thing as modules like L<Class::Accessor> and
917 L<Class::MethodMaker>. That being said there are very few modules on CPAN
918 with similar goals to this module. The one I have found which is most
919 like this module is L<Class::Meta>, although it's philosophy and the MOP it
920 creates are very different from this modules.
921
922 =head1 BUGS
923
924 All complex software has bugs lurking in it, and this module is no
925 exception. If you find a bug please either email me, or add the bug
926 to cpan-RT.
927
928 =head1 ACKNOWLEDGEMENTS
929
930 =over 4
931
932 =item Rob Kinyon
933
934 Thanks to Rob for actually getting the development of this module kick-started.
935
936 =back
937
938 =head1 AUTHORS
939
940 Stevan Little E<lt>stevan@iinteractive.comE<gt>
941
942 B<with contributions from:>
943
944 Brandon (blblack) Black
945
946 Guillermo (groditi) Roditi
947
948 Matt (mst) Trout
949
950 Rob (robkinyon) Kinyon
951
952 Yuval (nothingmuch) Kogman
953
954 Scott (konobi) McWhirter
955
956 =head1 COPYRIGHT AND LICENSE
957
958 Copyright 2006-2008 by Infinity Interactive, Inc.
959
960 L<http://www.iinteractive.com>
961
962 This library is free software; you can redistribute it and/or modify
963 it under the same terms as Perl itself.
964
965 =cut