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