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