fixing version numbers and writing the changelog
[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 ();
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.32';
17
18 ## ----------------------------------------------------------------------------
19 ## Setting up our environment ...
20 ## ----------------------------------------------------------------------------
21 ## Class::MOP needs to have a few things in the global perl environment so 
22 ## that it can operate effectively. Those things are done here.
23 ## ----------------------------------------------------------------------------
24
25 # ... nothing yet actually ;)
26
27 ## ----------------------------------------------------------------------------
28 ## Bootstrapping 
29 ## ----------------------------------------------------------------------------
30 ## The code below here is to bootstrap our MOP with itself. This is also 
31 ## sometimes called "tying the knot". By doing this, we make it much easier
32 ## to extend the MOP through subclassing and such since now you can use the
33 ## MOP itself to extend itself. 
34 ## 
35 ## Yes, I know, thats weird and insane, but it's a good thing, trust me :)
36 ## ---------------------------------------------------------------------------- 
37
38 # We need to add in the meta-attributes here so that 
39 # any subclass of Class::MOP::* will be able to 
40 # inherit them using &construct_instance
41
42 ## Class::MOP::Package
43
44 Class::MOP::Package->meta->add_attribute(
45     Class::MOP::Attribute->new('$:package' => (
46         reader   => {
47             # NOTE: we need to do this in order 
48             # for the instance meta-object to 
49             # not fall into meta-circular death
50             'name' => sub { (shift)->{'$:package'} }
51         },
52         init_arg => ':package',
53     ))
54 );
55
56 Class::MOP::Package->meta->add_attribute(
57     Class::MOP::Attribute->new('%:namespace' => (
58         reader => {
59             'namespace' => sub { (shift)->{'%:namespace'} }
60         },
61         default => sub {
62             my ($class) = @_;
63             no strict 'refs';
64             return \%{$class->name . '::'};
65         },
66         # NOTE:
67         # protect this from silliness 
68         init_arg => '!............( DO NOT DO THIS )............!',
69     ))
70 );
71
72 # NOTE:
73 # use the metaclass to construct the meta-package
74 # which is a superclass of the metaclass itself :P
75 Class::MOP::Package->meta->add_method('initialize' => sub {
76     my $class        = shift;
77     my $package_name = shift;
78     $class->meta->new_object(':package' => $package_name, @_);  
79 });
80
81 ## Class::MOP::Class
82
83 Class::MOP::Class->meta->add_attribute(
84     Class::MOP::Attribute->new('%:attributes' => (
85         reader   => {
86             # NOTE: we need to do this in order 
87             # for the instance meta-object to 
88             # not fall into meta-circular death            
89             'get_attribute_map' => sub { (shift)->{'%:attributes'} }
90         },
91         init_arg => ':attributes',
92         default  => sub { {} }
93     ))
94 );
95
96 Class::MOP::Class->meta->add_attribute(
97     Class::MOP::Attribute->new('$:attribute_metaclass' => (
98         reader   => 'attribute_metaclass',
99         init_arg => ':attribute_metaclass',
100         default  => 'Class::MOP::Attribute',
101     ))
102 );
103
104 Class::MOP::Class->meta->add_attribute(
105     Class::MOP::Attribute->new('$:method_metaclass' => (
106         reader   => 'method_metaclass',
107         init_arg => ':method_metaclass',
108         default  => 'Class::MOP::Method',        
109     ))
110 );
111
112 Class::MOP::Class->meta->add_attribute(
113     Class::MOP::Attribute->new('$:instance_metaclass' => (
114         reader   => {
115             # NOTE: we need to do this in order 
116             # for the instance meta-object to 
117             # not fall into meta-circular death            
118             'instance_metaclass' => sub { (shift)->{'$:instance_metaclass'} }
119         },
120         init_arg => ':instance_metaclass',
121         default  => 'Class::MOP::Instance',        
122     ))
123 );
124
125 # NOTE:
126 # we don't actually need to tie the knot with 
127 # Class::MOP::Class here, it is actually handled 
128 # within Class::MOP::Class itself in the 
129 # construct_class_instance method. 
130
131 ## Class::MOP::Attribute
132
133 Class::MOP::Attribute->meta->add_attribute(
134     Class::MOP::Attribute->new('name' => (
135         reader => {
136             # NOTE: we need to do this in order 
137             # for the instance meta-object to 
138             # not fall into meta-circular death            
139             'name' => sub { (shift)->{name} }
140         }
141     ))
142 );
143
144 Class::MOP::Attribute->meta->add_attribute(
145     Class::MOP::Attribute->new('associated_class' => (
146         reader => {
147             # NOTE: we need to do this in order 
148             # for the instance meta-object to 
149             # not fall into meta-circular death            
150             'associated_class' => sub { (shift)->{associated_class} }
151         }
152     ))
153 );
154
155 Class::MOP::Attribute->meta->add_attribute(
156     Class::MOP::Attribute->new('accessor' => (
157         reader    => 'accessor',
158         predicate => 'has_accessor',
159     ))
160 );
161
162 Class::MOP::Attribute->meta->add_attribute(
163     Class::MOP::Attribute->new('reader' => (
164         reader    => 'reader',
165         predicate => 'has_reader',
166     ))
167 );
168
169 Class::MOP::Attribute->meta->add_attribute(
170     Class::MOP::Attribute->new('writer' => (
171         reader    => 'writer',
172         predicate => 'has_writer',
173     ))
174 );
175
176 Class::MOP::Attribute->meta->add_attribute(
177     Class::MOP::Attribute->new('predicate' => (
178         reader    => 'predicate',
179         predicate => 'has_predicate',
180     ))
181 );
182
183 Class::MOP::Attribute->meta->add_attribute(
184     Class::MOP::Attribute->new('clearer' => (
185         reader    => 'clearer',
186         predicate => 'has_clearer',
187     ))
188 );
189
190 Class::MOP::Attribute->meta->add_attribute(
191     Class::MOP::Attribute->new('init_arg' => (
192         reader    => 'init_arg',
193         predicate => 'has_init_arg',
194     ))
195 );
196
197 Class::MOP::Attribute->meta->add_attribute(
198     Class::MOP::Attribute->new('default' => (
199         # default has a custom 'reader' method ...
200         predicate => 'has_default',
201     ))
202 );
203
204
205 # NOTE: (meta-circularity)
206 # This should be one of the last things done
207 # it will "tie the knot" with Class::MOP::Attribute
208 # so that it uses the attributes meta-objects 
209 # to construct itself. 
210 Class::MOP::Attribute->meta->add_method('new' => sub {
211     my $class   = shift;
212     my $name    = shift;
213     my %options = @_;    
214         
215     (defined $name && $name)
216         || confess "You must provide a name for the attribute";
217     $options{init_arg} = $name 
218         if not exists $options{init_arg};
219
220     # return the new object
221     $class->meta->new_object(name => $name, %options);
222 });
223
224 Class::MOP::Attribute->meta->add_method('clone' => sub {
225     my $self  = shift;
226     $self->meta->clone_object($self, @_);  
227 });
228
229 ## Try and close Class::MOP::*
230
231 Class::MOP::Package  ->meta->make_immutable(inline_constructor => 0);
232 Class::MOP::Module   ->meta->make_immutable(inline_constructor => 0);
233 Class::MOP::Class    ->meta->make_immutable(inline_constructor => 0);
234 Class::MOP::Attribute->meta->make_immutable(inline_constructor => 0);
235 Class::MOP::Method   ->meta->make_immutable(inline_constructor => 0);
236 Class::MOP::Instance ->meta->make_immutable(inline_constructor => 0);
237
238
239 1;
240
241 __END__
242
243 =pod
244
245 =head1 NAME 
246
247 Class::MOP - A Meta Object Protocol for Perl 5
248
249 =head1 SYNOPSIS
250
251   # ... This will come later, for now see
252   # the other SYNOPSIS for more information
253
254 =head1 DESCRIPTON
255
256 This module is an attempt to create a meta object protocol for the 
257 Perl 5 object system. It makes no attempt to change the behavior or 
258 characteristics of the Perl 5 object system, only to create a 
259 protocol for its manipulation and introspection.
260
261 That said, it does attempt to create the tools for building a rich 
262 set of extensions to the Perl 5 object system. Every attempt has been 
263 made for these tools to keep to the spirit of the Perl 5 object 
264 system that we all know and love.
265
266 This documentation is admittedly sparse on details, as time permits 
267 I will try to improve them. For now, I suggest looking at the items 
268 listed in the L<SEE ALSO> section for more information. In particular 
269 the book "The Art of the Meta Object Protocol" was very influential 
270 in the development of this system.
271
272 =head2 What is a Meta Object Protocol?
273
274 A meta object protocol is an API to an object system. 
275
276 To be more specific, it is a set of abstractions of the components of 
277 an object system (typically things like; classes, object, methods, 
278 object attributes, etc.). These abstractions can then be used to both 
279 inspect and manipulate the object system which they describe.
280
281 It can be said that there are two MOPs for any object system; the 
282 implicit MOP, and the explicit MOP. The implicit MOP handles things 
283 like method dispatch or inheritance, which happen automatically as 
284 part of how the object system works. The explicit MOP typically 
285 handles the introspection/reflection features of the object system. 
286 All object systems have implicit MOPs, without one, they would not 
287 work. Explict MOPs however as less common, and depending on the 
288 language can vary from restrictive (Reflection in Java or C#) to 
289 wide open (CLOS is a perfect example). 
290
291 =head2 Yet Another Class Builder!! Why?
292
293 This is B<not> a class builder so much as it is a I<class builder 
294 B<builder>>. My intent is that an end user does not use this module 
295 directly, but instead this module is used by module authors to 
296 build extensions and features onto the Perl 5 object system. 
297
298 =head2 Who is this module for?
299
300 This module is specifically for anyone who has ever created or 
301 wanted to create a module for the Class:: namespace. The tools which 
302 this module will provide will hopefully make it easier to do more 
303 complex things with Perl 5 classes by removing such barriers as 
304 the need to hack the symbol tables, or understand the fine details 
305 of method dispatch. 
306
307 =head2 What changes do I have to make to use this module?
308
309 This module was designed to be as unintrusive as possible. Many of 
310 its features are accessible without B<any> change to your existsing 
311 code at all. It is meant to be a compliment to your existing code and 
312 not an intrusion on your code base. Unlike many other B<Class::> 
313 modules, this module B<does not> require you subclass it, or even that 
314 you C<use> it in within your module's package. 
315
316 The only features which requires additions to your code are the 
317 attribute handling and instance construction features, and these are
318 both completely optional features. The only reason for this is because 
319 Perl 5's object system does not actually have these features built 
320 in. More information about this feature can be found below.
321
322 =head2 A Note about Performance?
323
324 It is a common misconception that explict MOPs are performance drains. 
325 But this is not a universal truth at all, it is an side-effect of 
326 specific implementations. For instance, using Java reflection is much 
327 slower because the JVM cannot take advantage of any compiler 
328 optimizations, and the JVM has to deal with much more runtime type 
329 information as well. Reflection in C# is marginally better as it was 
330 designed into the language and runtime (the CLR). In contrast, CLOS 
331 (the Common Lisp Object System) was built to support an explicit MOP, 
332 and so performance is tuned for it. 
333
334 This library in particular does it's absolute best to avoid putting 
335 B<any> drain at all upon your code's performance. In fact, by itself 
336 it does nothing to affect your existing code. So you only pay for 
337 what you actually use.
338
339 =head2 About Metaclass compatibility
340
341 This module makes sure that all metaclasses created are both upwards 
342 and downwards compatible. The topic of metaclass compatibility is 
343 highly esoteric and is something only encountered when doing deep and 
344 involved metaclass hacking. There are two basic kinds of metaclass 
345 incompatibility; upwards and downwards. 
346
347 Upwards metaclass compatibility means that the metaclass of a 
348 given class is either the same as (or a subclass of) all of the 
349 class's ancestors.
350
351 Downward metaclass compatibility means that the metaclasses of a 
352 given class's anscestors are all either the same as (or a subclass 
353 of) that metaclass.
354
355 Here is a diagram showing a set of two classes (C<A> and C<B>) and 
356 two metaclasses (C<Meta::A> and C<Meta::B>) which have correct  
357 metaclass compatibility both upwards and downwards.
358
359     +---------+     +---------+
360     | Meta::A |<----| Meta::B |      <....... (instance of  )
361     +---------+     +---------+      <------- (inherits from)  
362          ^               ^
363          :               :
364     +---------+     +---------+
365     |    A    |<----|    B    |
366     +---------+     +---------+
367
368 As I said this is a highly esoteric topic and one you will only run 
369 into if you do a lot of subclassing of B<Class::MOP::Class>. If you 
370 are interested in why this is an issue see the paper 
371 I<Uniform and safe metaclass composition> linked to in the 
372 L<SEE ALSO> section of this document.
373
374 =head2 Using custom metaclasses
375
376 Always use the metaclass pragma when using a custom metaclass, this 
377 will ensure the proper initialization order and not accidentely 
378 create an incorrect type of metaclass for you. This is a very rare 
379 problem, and one which can only occur if you are doing deep metaclass 
380 programming. So in other words, don't worry about it.
381
382 =head1 PROTOCOLS
383
384 The protocol is divided into 3 main sub-protocols:
385
386 =over 4
387
388 =item The Class protocol
389
390 This provides a means of manipulating and introspecting a Perl 5 
391 class. It handles all of symbol table hacking for you, and provides 
392 a rich set of methods that go beyond simple package introspection.
393
394 See L<Class::MOP::Class> for more details.
395
396 =item The Attribute protocol
397
398 This provides a consistent represenation for an attribute of a 
399 Perl 5 class. Since there are so many ways to create and handle 
400 atttributes in Perl 5 OO, this attempts to provide as much of a 
401 unified approach as possible, while giving the freedom and 
402 flexibility to subclass for specialization.
403
404 See L<Class::MOP::Attribute> for more details.
405
406 =item The Method protocol
407
408 This provides a means of manipulating and introspecting methods in 
409 the Perl 5 object system. As with attributes, there are many ways to 
410 approach this topic, so we try to keep it pretty basic, while still 
411 making it possible to extend the system in many ways.
412
413 See L<Class::MOP::Method> for more details.
414
415 =back
416
417 =head1 SEE ALSO
418
419 =head2 Books
420
421 There are very few books out on Meta Object Protocols and Metaclasses 
422 because it is such an esoteric topic. The following books are really 
423 the only ones I have found. If you know of any more, B<I<please>> 
424 email me and let me know, I would love to hear about them.
425
426 =over 4
427
428 =item "The Art of the Meta Object Protocol"
429
430 =item "Advances in Object-Oriented Metalevel Architecture and Reflection"
431
432 =item "Putting MetaClasses to Work"
433
434 =item "Smalltalk: The Language"
435
436 =back
437
438 =head2 Papers
439
440 =over 4
441
442 =item Uniform and safe metaclass composition
443
444 An excellent paper by the people who brought us the original Traits paper. 
445 This paper is on how Traits can be used to do safe metaclass composition, 
446 and offers an excellent introduction section which delves into the topic of 
447 metaclass compatibility.
448
449 L<http://www.iam.unibe.ch/~scg/Archive/Papers/Duca05ySafeMetaclassTrait.pdf>
450
451 =item Safe Metaclass Programming
452
453 This paper seems to precede the above paper, and propose a mix-in based 
454 approach as opposed to the Traits based approach. Both papers have similar 
455 information on the metaclass compatibility problem space. 
456
457 L<http://citeseer.ist.psu.edu/37617.html>
458
459 =back
460
461 =head2 Prior Art
462
463 =over 4
464
465 =item The Perl 6 MetaModel work in the Pugs project
466
467 =over 4
468
469 =item L<http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel>
470
471 =item L<http://svn.openfoundry.org/pugs/perl5/Perl6-ObjectSpace>
472
473 =back
474
475 =back
476
477 =head1 SIMILAR MODULES
478
479 As I have said above, this module is a class-builder-builder, so it is 
480 not the same thing as modules like L<Class::Accessor> and 
481 L<Class::MethodMaker>. That being said there are very few modules on CPAN 
482 with similar goals to this module. The one I have found which is most 
483 like this module is L<Class::Meta>, although it's philosophy and the MOP it 
484 creates are very different from this modules. 
485
486 =head1 BUGS
487
488 All complex software has bugs lurking in it, and this module is no 
489 exception. If you find a bug please either email me, or add the bug
490 to cpan-RT.
491
492 =head1 CODE COVERAGE
493
494 I use L<Devel::Cover> to test the code coverage of my tests, below is the 
495 L<Devel::Cover> report on this module's test suite.
496
497  ---------------------------- ------ ------ ------ ------ ------ ------ ------
498  File                           stmt   bran   cond    sub    pod   time  total
499  ---------------------------- ------ ------ ------ ------ ------ ------ ------
500  Class/MOP.pm                  100.0  100.0  100.0  100.0    n/a   19.8  100.0
501  Class/MOP/Attribute.pm        100.0  100.0   91.7   61.2  100.0   14.3   87.9
502  Class/MOP/Class.pm             97.6   91.3   77.3   98.4  100.0   56.4   93.2
503  Class/MOP/Instance.pm          91.1   75.0   33.3   91.7  100.0    6.8   90.7
504  Class/MOP/Method.pm            97.6   60.0   52.9   76.9  100.0    1.6   82.6
505  metaclass.pm                  100.0  100.0   83.3  100.0    n/a    1.0   97.7
506  ---------------------------- ------ ------ ------ ------ ------ ------ ------
507  Total                          97.5   88.5   75.5   82.8  100.0  100.0   91.2
508  ---------------------------- ------ ------ ------ ------ ------ ------ ------
509
510 =head1 ACKNOWLEDGEMENTS
511
512 =over 4
513
514 =item Rob Kinyon E<lt>rob@iinteractive.comE<gt>
515
516 Thanks to Rob for actually getting the development of this module kick-started. 
517
518 =back
519
520 =head1 AUTHORS
521
522 Stevan Little E<lt>stevan@iinteractive.comE<gt>
523
524 Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
525
526 =head1 COPYRIGHT AND LICENSE
527
528 Copyright 2006 by Infinity Interactive, Inc.
529
530 L<http://www.iinteractive.com>
531
532 This library is free software; you can redistribute it and/or modify
533 it under the same terms as Perl itself. 
534
535 =cut