more misc cleanup
[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
b9d9fc0b 510This will return an hash of all the metaclass instances that have
511been cached by B<Class::MOP::Class> keyed by the package name.
512
be7677c7 513=item B<get_all_metaclass_instances>
514
b9d9fc0b 515This will return an array of all the metaclass instances that have
516been cached by B<Class::MOP::Class>.
517
be7677c7 518=item B<get_all_metaclass_names>
519
b9d9fc0b 520This will return an array of all the metaclass names that have
521been cached by B<Class::MOP::Class>.
522
be7677c7 523=item B<get_metaclass_by_name ($name)>
524
525=item B<store_metaclass_by_name ($name, $meta)>
526
527=item B<weaken_metaclass ($name)>
528
529=item B<does_metaclass_exist ($name)>
530
531=item B<remove_metaclass_by_name ($name)>
532
533=back
534
552e3d24 535=head1 SEE ALSO
8b978dd5 536
552e3d24 537=head2 Books
8b978dd5 538
a2e85e6c 539There are very few books out on Meta Object Protocols and Metaclasses
540because it is such an esoteric topic. The following books are really
541the only ones I have found. If you know of any more, B<I<please>>
542email me and let me know, I would love to hear about them.
543
8b978dd5 544=over 4
545
552e3d24 546=item "The Art of the Meta Object Protocol"
8b978dd5 547
552e3d24 548=item "Advances in Object-Oriented Metalevel Architecture and Reflection"
8b978dd5 549
b51af7f9 550=item "Putting MetaClasses to Work"
551
a2e85e6c 552=item "Smalltalk: The Language"
553
94b19069 554=back
555
550d56db 556=head2 Papers
557
558=over 4
559
560=item Uniform and safe metaclass composition
561
562An excellent paper by the people who brought us the original Traits paper.
563This paper is on how Traits can be used to do safe metaclass composition,
564and offers an excellent introduction section which delves into the topic of
565metaclass compatibility.
566
567L<http://www.iam.unibe.ch/~scg/Archive/Papers/Duca05ySafeMetaclassTrait.pdf>
568
569=item Safe Metaclass Programming
570
571This paper seems to precede the above paper, and propose a mix-in based
572approach as opposed to the Traits based approach. Both papers have similar
573information on the metaclass compatibility problem space.
574
575L<http://citeseer.ist.psu.edu/37617.html>
576
577=back
578
552e3d24 579=head2 Prior Art
8b978dd5 580
581=over 4
582
7184ca14 583=item The Perl 6 MetaModel work in the Pugs project
8b978dd5 584
585=over 4
586
552e3d24 587=item L<http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel>
8b978dd5 588
552e3d24 589=item L<http://svn.openfoundry.org/pugs/perl5/Perl6-ObjectSpace>
8b978dd5 590
591=back
592
94b19069 593=back
594
a2e85e6c 595=head1 SIMILAR MODULES
596
597As I have said above, this module is a class-builder-builder, so it is
598not the same thing as modules like L<Class::Accessor> and
599L<Class::MethodMaker>. That being said there are very few modules on CPAN
600with similar goals to this module. The one I have found which is most
550d56db 601like this module is L<Class::Meta>, although it's philosophy and the MOP it
602creates are very different from this modules.
94b19069 603
a2e85e6c 604=head1 BUGS
605
606All complex software has bugs lurking in it, and this module is no
607exception. If you find a bug please either email me, or add the bug
608to cpan-RT.
609
22286063 610=head1 CODE COVERAGE
611
612I use L<Devel::Cover> to test the code coverage of my tests, below is the
613L<Devel::Cover> report on this module's test suite.
614
615 ---------------------------- ------ ------ ------ ------ ------ ------ ------
616 File stmt bran cond sub pod time total
617 ---------------------------- ------ ------ ------ ------ ------ ------ ------
b9d9fc0b 618 Class/MOP.pm 78.0 87.5 55.6 71.4 100.0 12.4 76.8
619 Class/MOP/Attribute.pm 83.4 75.6 86.7 94.4 100.0 8.9 85.2
620 Class/MOP/Class.pm 96.9 75.8 43.2 98.0 100.0 55.3 83.6
621 Class/MOP/Class/Immutable.pm 88.5 53.8 n/a 95.8 100.0 1.1 84.7
622 Class/MOP/Instance.pm 87.9 75.0 33.3 89.7 100.0 10.1 89.1
623 Class/MOP/Method.pm 97.6 60.0 57.9 76.9 100.0 1.5 82.8
624 Class/MOP/Module.pm 87.5 n/a 11.1 83.3 100.0 0.3 66.7
625 Class/MOP/Object.pm 100.0 n/a 33.3 100.0 100.0 0.1 89.5
626 Class/MOP/Package.pm 95.1 69.0 33.3 100.0 100.0 9.9 85.5
627 metaclass.pm 100.0 100.0 83.3 100.0 n/a 0.5 97.7
22286063 628 ---------------------------- ------ ------ ------ ------ ------ ------ ------
b9d9fc0b 629 Total 91.5 72.1 48.8 90.7 100.0 100.0 84.2
22286063 630 ---------------------------- ------ ------ ------ ------ ------ ------ ------
631
a2e85e6c 632=head1 ACKNOWLEDGEMENTS
633
634=over 4
635
b9d9fc0b 636=item Rob Kinyon
a2e85e6c 637
638Thanks to Rob for actually getting the development of this module kick-started.
639
640=back
641
1a09d9cc 642=head1 AUTHORS
94b19069 643
a2e85e6c 644Stevan Little E<lt>stevan@iinteractive.comE<gt>
552e3d24 645
1a09d9cc 646Yuval Kogman E<lt>nothingmuch@woobling.comE<gt>
647
94b19069 648=head1 COPYRIGHT AND LICENSE
649
650Copyright 2006 by Infinity Interactive, Inc.
651
652L<http://www.iinteractive.com>
653
654This library is free software; you can redistribute it and/or modify
655it under the same terms as Perl itself.
656
657=cut