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