builder changes. sorry about diff noise, my editor ate trailing whitespace :(
[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
c23184fc 14use Class::MOP::Immutable;
857f87a7 15
565f0cbb 16our $VERSION = '0.43';
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?
1d68af04 24 my %METAS;
25
26 # means of accessing all the metaclasses that have
be7677c7 27 # been initialized thus far (for mugwumps obj browser)
1d68af04 28 sub get_all_metaclasses { %METAS }
29 sub get_all_metaclass_instances { values %METAS }
30 sub get_all_metaclass_names { keys %METAS }
be7677c7 31 sub get_metaclass_by_name { $METAS{$_[0]} }
1d68af04 32 sub store_metaclass_by_name { $METAS{$_[0]} = $_[1] }
33 sub weaken_metaclass { weaken($METAS{$_[0]}) }
be7677c7 34 sub does_metaclass_exist { exists $METAS{$_[0]} && defined $METAS{$_[0]} }
1d68af04 35 sub remove_metaclass_by_name { $METAS{$_[0]} = undef }
36
be7677c7 37 # NOTE:
1d68af04 38 # We only cache metaclasses, meaning instances of
39 # Class::MOP::Class. We do not cache instance of
be7677c7 40 # Class::MOP::Package or Class::MOP::Module. Mostly
1d68af04 41 # because I don't yet see a good reason to do so.
be7677c7 42}
43
448b6e55 44sub load_class {
45 my $class = shift;
1d68af04 46 # see if this is already
448b6e55 47 # loaded in the symbol table
48 return 1 if is_class_loaded($class);
49 # otherwise require it ...
50 my $file = $class . '.pm';
51 $file =~ s{::}{/}g;
52 eval { CORE::require($file) };
53 confess "Could not load class ($class) because : $@" if $@;
54 unless (does_metaclass_exist($class)) {
55 eval { Class::MOP::Class->initialize($class) };
1d68af04 56 confess "Could not initialize class ($class) because : $@" if $@;
448b6e55 57 }
58 1; # return true if it worked
59}
60
61sub is_class_loaded {
1d68af04 62 my $class = shift;
63 no strict 'refs';
64 return 1 if defined ${"${class}::VERSION"} || defined @{"${class}::ISA"};
65 foreach (keys %{"${class}::"}) {
66 next if substr($_, -2, 2) eq '::';
67 return 1 if defined &{"${class}::$_"};
68 }
69 return 0;
448b6e55 70}
71
72
aa448b16 73## ----------------------------------------------------------------------------
74## Setting up our environment ...
75## ----------------------------------------------------------------------------
1d68af04 76## Class::MOP needs to have a few things in the global perl environment so
aa448b16 77## that it can operate effectively. Those things are done here.
78## ----------------------------------------------------------------------------
79
3bf7644b 80# ... nothing yet actually ;)
8b978dd5 81
b51af7f9 82## ----------------------------------------------------------------------------
1d68af04 83## Bootstrapping
b51af7f9 84## ----------------------------------------------------------------------------
1d68af04 85## The code below here is to bootstrap our MOP with itself. This is also
b51af7f9 86## sometimes called "tying the knot". By doing this, we make it much easier
87## to extend the MOP through subclassing and such since now you can use the
1d68af04 88## MOP itself to extend itself.
89##
b51af7f9 90## Yes, I know, thats weird and insane, but it's a good thing, trust me :)
1d68af04 91## ----------------------------------------------------------------------------
727919c5 92
1d68af04 93# We need to add in the meta-attributes here so that
94# any subclass of Class::MOP::* will be able to
727919c5 95# inherit them using &construct_instance
96
f0480c45 97## --------------------------------------------------------
6d5355c3 98## Class::MOP::Package
727919c5 99
6d5355c3 100Class::MOP::Package->meta->add_attribute(
c23184fc 101 Class::MOP::Attribute->new('$!package' => (
b880e0de 102 reader => {
1d68af04 103 # NOTE: we need to do this in order
104 # for the instance meta-object to
b880e0de 105 # not fall into meta-circular death
1d68af04 106 #
ce2ae40f 107 # we just alias the original method
1d68af04 108 # rather than re-produce it here
ce2ae40f 109 'name' => \&Class::MOP::Package::name
b880e0de 110 },
c23184fc 111 init_arg => 'package',
727919c5 112 ))
113);
114
a5e51f0b 115Class::MOP::Package->meta->add_attribute(
c23184fc 116 Class::MOP::Attribute->new('%!namespace' => (
a5e51f0b 117 reader => {
56dcfc1a 118 # NOTE:
ce2ae40f 119 # we just alias the original method
120 # rather than re-produce it here
121 'namespace' => \&Class::MOP::Package::namespace
a5e51f0b 122 },
123 # NOTE:
1d68af04 124 # protect this from silliness
a2ee6c61 125 init_arg => '!............( DO NOT DO THIS )............!',
c4260b45 126 default => sub { \undef }
a5e51f0b 127 ))
128);
129
9d6dce77 130# NOTE:
131# use the metaclass to construct the meta-package
132# which is a superclass of the metaclass itself :P
133Class::MOP::Package->meta->add_method('initialize' => sub {
134 my $class = shift;
135 my $package_name = shift;
1d68af04 136 $class->meta->new_object('package' => $package_name, @_);
9d6dce77 137});
138
f0480c45 139## --------------------------------------------------------
140## Class::MOP::Module
141
142# NOTE:
1d68af04 143# yeah this is kind of stretching things a bit,
f0480c45 144# but truthfully the version should be an attribute
1d68af04 145# of the Module, the weirdness comes from having to
146# stick to Perl 5 convention and store it in the
147# $VERSION package variable. Basically if you just
148# squint at it, it will look how you want it to look.
f0480c45 149# Either as a package variable, or as a attribute of
150# the metaclass, isn't abstraction great :)
151
152Class::MOP::Module->meta->add_attribute(
c23184fc 153 Class::MOP::Attribute->new('$!version' => (
f0480c45 154 reader => {
ce2ae40f 155 # NOTE:
156 # we just alias the original method
1d68af04 157 # rather than re-produce it here
ce2ae40f 158 'version' => \&Class::MOP::Module::version
f0480c45 159 },
160 # NOTE:
1d68af04 161 # protect this from silliness
f0480c45 162 init_arg => '!............( DO NOT DO THIS )............!',
c4260b45 163 default => sub { \undef }
f0480c45 164 ))
165);
166
167# NOTE:
1d68af04 168# By following the same conventions as version here,
169# we are opening up the possibility that people can
170# use the $AUTHORITY in non-Class::MOP modules as
171# well.
f0480c45 172
173Class::MOP::Module->meta->add_attribute(
c23184fc 174 Class::MOP::Attribute->new('$!authority' => (
f0480c45 175 reader => {
ce2ae40f 176 # NOTE:
177 # we just alias the original method
1d68af04 178 # rather than re-produce it here
ce2ae40f 179 'authority' => \&Class::MOP::Module::authority
1d68af04 180 },
f0480c45 181 # NOTE:
1d68af04 182 # protect this from silliness
f0480c45 183 init_arg => '!............( DO NOT DO THIS )............!',
c4260b45 184 default => sub { \undef }
f0480c45 185 ))
186);
187
188## --------------------------------------------------------
6d5355c3 189## Class::MOP::Class
190
727919c5 191Class::MOP::Class->meta->add_attribute(
c23184fc 192 Class::MOP::Attribute->new('%!attributes' => (
f7259199 193 reader => {
1d68af04 194 # NOTE: we need to do this in order
195 # for the instance meta-object to
196 # not fall into meta-circular death
197 #
ce2ae40f 198 # we just alias the original method
1d68af04 199 # rather than re-produce it here
ce2ae40f 200 'get_attribute_map' => \&Class::MOP::Class::get_attribute_map
f7259199 201 },
c23184fc 202 init_arg => 'attributes',
727919c5 203 default => sub { {} }
204 ))
205);
206
351bd7d4 207Class::MOP::Class->meta->add_attribute(
c23184fc 208 Class::MOP::Attribute->new('%!methods' => (
209 init_arg => 'methods',
1d68af04 210 reader => {
ce2ae40f 211 # NOTE:
212 # we just alias the original method
1d68af04 213 # rather than re-produce it here
ce2ae40f 214 'get_method_map' => \&Class::MOP::Class::get_method_map
92330ee2 215 },
7855ddba 216 default => sub { {} }
c4260b45 217 ))
218);
219
220Class::MOP::Class->meta->add_attribute(
c23184fc 221 Class::MOP::Attribute->new('@!superclasses' => (
222 accessor => {
223 # NOTE:
224 # we just alias the original method
1d68af04 225 # rather than re-produce it here
c23184fc 226 'superclasses' => \&Class::MOP::Class::superclasses
227 },
228 # NOTE:
1d68af04 229 # protect this from silliness
c23184fc 230 init_arg => '!............( DO NOT DO THIS )............!',
231 default => sub { \undef }
232 ))
233);
234
235Class::MOP::Class->meta->add_attribute(
236 Class::MOP::Attribute->new('$!attribute_metaclass' => (
1d68af04 237 reader => {
6d2118a4 238 # NOTE:
239 # we just alias the original method
1d68af04 240 # rather than re-produce it here
6d2118a4 241 'attribute_metaclass' => \&Class::MOP::Class::attribute_metaclass
1d68af04 242 },
c23184fc 243 init_arg => 'attribute_metaclass',
351bd7d4 244 default => 'Class::MOP::Attribute',
245 ))
246);
247
248Class::MOP::Class->meta->add_attribute(
c23184fc 249 Class::MOP::Attribute->new('$!method_metaclass' => (
1d68af04 250 reader => {
6d2118a4 251 # NOTE:
252 # we just alias the original method
1d68af04 253 # rather than re-produce it here
6d2118a4 254 'method_metaclass' => \&Class::MOP::Class::method_metaclass
255 },
c23184fc 256 init_arg => 'method_metaclass',
1d68af04 257 default => 'Class::MOP::Method',
351bd7d4 258 ))
259);
260
2bab2be6 261Class::MOP::Class->meta->add_attribute(
c23184fc 262 Class::MOP::Attribute->new('$!instance_metaclass' => (
b880e0de 263 reader => {
1d68af04 264 # NOTE: we need to do this in order
265 # for the instance meta-object to
266 # not fall into meta-circular death
267 #
ce2ae40f 268 # we just alias the original method
1d68af04 269 # rather than re-produce it here
ce2ae40f 270 'instance_metaclass' => \&Class::MOP::Class::instance_metaclass
b880e0de 271 },
c23184fc 272 init_arg => 'instance_metaclass',
1d68af04 273 default => 'Class::MOP::Instance',
2bab2be6 274 ))
275);
276
9d6dce77 277# NOTE:
1d68af04 278# we don't actually need to tie the knot with
279# Class::MOP::Class here, it is actually handled
280# within Class::MOP::Class itself in the
281# construct_class_instance method.
9d6dce77 282
f0480c45 283## --------------------------------------------------------
727919c5 284## Class::MOP::Attribute
285
7b31baf4 286Class::MOP::Attribute->meta->add_attribute(
c23184fc 287 Class::MOP::Attribute->new('$!name' => (
288 init_arg => 'name',
289 reader => {
1d68af04 290 # NOTE: we need to do this in order
291 # for the instance meta-object to
292 # not fall into meta-circular death
293 #
ce2ae40f 294 # we just alias the original method
1d68af04 295 # rather than re-produce it here
ce2ae40f 296 'name' => \&Class::MOP::Attribute::name
b880e0de 297 }
7b31baf4 298 ))
299);
300
301Class::MOP::Attribute->meta->add_attribute(
c23184fc 302 Class::MOP::Attribute->new('$!associated_class' => (
303 init_arg => 'associated_class',
304 reader => {
1d68af04 305 # NOTE: we need to do this in order
306 # for the instance meta-object to
307 # not fall into meta-circular death
308 #
ce2ae40f 309 # we just alias the original method
1d68af04 310 # rather than re-produce it here
ce2ae40f 311 'associated_class' => \&Class::MOP::Attribute::associated_class
b880e0de 312 }
7b31baf4 313 ))
314);
315
316Class::MOP::Attribute->meta->add_attribute(
c23184fc 317 Class::MOP::Attribute->new('$!accessor' => (
318 init_arg => 'accessor',
6d2118a4 319 reader => { 'accessor' => \&Class::MOP::Attribute::accessor },
320 predicate => { 'has_accessor' => \&Class::MOP::Attribute::has_accessor },
7b31baf4 321 ))
322);
323
324Class::MOP::Attribute->meta->add_attribute(
c23184fc 325 Class::MOP::Attribute->new('$!reader' => (
326 init_arg => 'reader',
6d2118a4 327 reader => { 'reader' => \&Class::MOP::Attribute::reader },
328 predicate => { 'has_reader' => \&Class::MOP::Attribute::has_reader },
7b31baf4 329 ))
330);
331
332Class::MOP::Attribute->meta->add_attribute(
c23184fc 333 Class::MOP::Attribute->new('$!writer' => (
334 init_arg => 'writer',
6d2118a4 335 reader => { 'writer' => \&Class::MOP::Attribute::writer },
336 predicate => { 'has_writer' => \&Class::MOP::Attribute::has_writer },
7b31baf4 337 ))
338);
339
340Class::MOP::Attribute->meta->add_attribute(
c23184fc 341 Class::MOP::Attribute->new('$!predicate' => (
342 init_arg => 'predicate',
6d2118a4 343 reader => { 'predicate' => \&Class::MOP::Attribute::predicate },
344 predicate => { 'has_predicate' => \&Class::MOP::Attribute::has_predicate },
7b31baf4 345 ))
346);
347
348Class::MOP::Attribute->meta->add_attribute(
c23184fc 349 Class::MOP::Attribute->new('$!clearer' => (
350 init_arg => 'clearer',
6d2118a4 351 reader => { 'clearer' => \&Class::MOP::Attribute::clearer },
352 predicate => { 'has_clearer' => \&Class::MOP::Attribute::has_clearer },
7d28758b 353 ))
354);
355
356Class::MOP::Attribute->meta->add_attribute(
1d68af04 357 Class::MOP::Attribute->new('$!builder' => (
358 init_arg => 'builder',
359 reader => { 'builder' => \&Class::MOP::Attribute::builder },
360 predicate => { 'has_builder' => \&Class::MOP::Attribute::has_builder },
361 ))
362);
363
364Class::MOP::Attribute->meta->add_attribute(
c23184fc 365 Class::MOP::Attribute->new('$!init_arg' => (
366 init_arg => 'init_arg',
6d2118a4 367 reader => { 'init_arg' => \&Class::MOP::Attribute::init_arg },
368 predicate => { 'has_init_arg' => \&Class::MOP::Attribute::has_init_arg },
7b31baf4 369 ))
370);
371
372Class::MOP::Attribute->meta->add_attribute(
c23184fc 373 Class::MOP::Attribute->new('$!default' => (
374 init_arg => 'default',
7b31baf4 375 # default has a custom 'reader' method ...
1d68af04 376 predicate => { 'has_default' => \&Class::MOP::Attribute::has_default },
7b31baf4 377 ))
378);
379
3545c727 380Class::MOP::Attribute->meta->add_attribute(
c23184fc 381 Class::MOP::Attribute->new('@!associated_methods' => (
382 init_arg => 'associated_methods',
383 reader => { 'associated_methods' => \&Class::MOP::Attribute::associated_methods },
1d68af04 384 default => sub { [] }
3545c727 385 ))
386);
727919c5 387
388# NOTE: (meta-circularity)
389# This should be one of the last things done
390# it will "tie the knot" with Class::MOP::Attribute
1d68af04 391# so that it uses the attributes meta-objects
392# to construct itself.
727919c5 393Class::MOP::Attribute->meta->add_method('new' => sub {
394 my $class = shift;
395 my $name = shift;
1d68af04 396 my %options = @_;
397
727919c5 398 (defined $name && $name)
399 || confess "You must provide a name for the attribute";
1d68af04 400 $options{init_arg} = $name
5659d76e 401 if not exists $options{init_arg};
1d68af04 402
403 if(exists $options{builder}){
404 confess("builder must be a defined scalar value which is a method name")
405 if ref $options{builder} || !(defined $options{builder});
406 confess("Setting both default and builder is not allowed.")
407 if exists $options{default};
408 }
148b4697 409 (Class::MOP::Attribute::is_default_a_coderef(\%options))
1d68af04 410 || confess("References are not allowed as default values, you must ".
148b4697 411 "wrap then in a CODE reference (ex: sub { [] } and not [])")
1d68af04 412 if exists $options{default} && ref $options{default};
651955fb 413
5659d76e 414 # return the new object
415 $class->meta->new_object(name => $name, %options);
416});
417
418Class::MOP::Attribute->meta->add_method('clone' => sub {
a740253a 419 my $self = shift;
1d68af04 420 $self->meta->clone_object($self, @_);
727919c5 421});
422
f0480c45 423## --------------------------------------------------------
b6164407 424## Class::MOP::Method
425
426Class::MOP::Method->meta->add_attribute(
c23184fc 427 Class::MOP::Attribute->new('&!body' => (
428 init_arg => 'body',
429 reader => { 'body' => \&Class::MOP::Method::body },
b6164407 430 ))
431);
432
433## --------------------------------------------------------
434## Class::MOP::Method::Wrapped
435
436# NOTE:
1d68af04 437# the way this item is initialized, this
438# really does not follow the standard
439# practices of attributes, but we put
b6164407 440# it here for completeness
441Class::MOP::Method::Wrapped->meta->add_attribute(
c23184fc 442 Class::MOP::Attribute->new('%!modifier_table')
b6164407 443);
444
445## --------------------------------------------------------
565f0cbb 446## Class::MOP::Method::Generated
447
448Class::MOP::Method::Generated->meta->add_attribute(
449 Class::MOP::Attribute->new('$!is_inline' => (
450 init_arg => 'is_inline',
451 reader => { 'is_inline' => \&Class::MOP::Method::Generated::is_inline },
1d68af04 452 ))
565f0cbb 453);
454
455## --------------------------------------------------------
d90b42a6 456## Class::MOP::Method::Accessor
457
458Class::MOP::Method::Accessor->meta->add_attribute(
c23184fc 459 Class::MOP::Attribute->new('$!attribute' => (
460 init_arg => 'attribute',
1d68af04 461 reader => {
462 'associated_attribute' => \&Class::MOP::Method::Accessor::associated_attribute
d90b42a6 463 },
1d68af04 464 ))
d90b42a6 465);
466
467Class::MOP::Method::Accessor->meta->add_attribute(
c23184fc 468 Class::MOP::Attribute->new('$!accessor_type' => (
469 init_arg => 'accessor_type',
470 reader => { 'accessor_type' => \&Class::MOP::Method::Accessor::accessor_type },
1d68af04 471 ))
d90b42a6 472);
473
d90b42a6 474
475## --------------------------------------------------------
476## Class::MOP::Method::Constructor
477
478Class::MOP::Method::Constructor->meta->add_attribute(
c23184fc 479 Class::MOP::Attribute->new('%!options' => (
480 init_arg => 'options',
1d68af04 481 reader => {
482 'options' => \&Class::MOP::Method::Constructor::options
d90b42a6 483 },
1d68af04 484 ))
d90b42a6 485);
486
487Class::MOP::Method::Constructor->meta->add_attribute(
c23184fc 488 Class::MOP::Attribute->new('$!associated_metaclass' => (
489 init_arg => 'metaclass',
1d68af04 490 reader => {
491 'associated_metaclass' => \&Class::MOP::Method::Constructor::associated_metaclass
492 },
493 ))
d90b42a6 494);
495
496## --------------------------------------------------------
86482605 497## Class::MOP::Instance
498
499# NOTE:
1d68af04 500# these don't yet do much of anything, but are just
86482605 501# included for completeness
502
503Class::MOP::Instance->meta->add_attribute(
c23184fc 504 Class::MOP::Attribute->new('$!meta')
86482605 505);
506
507Class::MOP::Instance->meta->add_attribute(
c23184fc 508 Class::MOP::Attribute->new('@!slots')
86482605 509);
510
511## --------------------------------------------------------
f0480c45 512## Now close all the Class::MOP::* classes
4d47b77f 513
0b9372a2 514# NOTE:
1d68af04 515# we don't need to inline the
516# constructors or the accessors
517# this only lengthens the compile
518# time of the MOP, and gives us
0b9372a2 519# no actual benefits.
520
521$_->meta->make_immutable(
522 inline_constructor => 0,
523 inline_accessors => 0,
524) for qw/
1d68af04 525 Class::MOP::Package
526 Class::MOP::Module
527 Class::MOP::Class
528
0b9372a2 529 Class::MOP::Attribute
1d68af04 530 Class::MOP::Method
531 Class::MOP::Instance
532
533 Class::MOP::Object
0b9372a2 534
565f0cbb 535 Class::MOP::Method::Generated
1d68af04 536
ba38bf08 537 Class::MOP::Method::Accessor
1d68af04 538 Class::MOP::Method::Constructor
539 Class::MOP::Method::Wrapped
0b9372a2 540/;
b6164407 541
94b19069 5421;
543
544__END__
545
546=pod
547
1d68af04 548=head1 NAME
94b19069 549
550Class::MOP - A Meta Object Protocol for Perl 5
551
94b19069 552=head1 DESCRIPTON
553
1d68af04 554This module is an attempt to create a meta object protocol for the
555Perl 5 object system. It makes no attempt to change the behavior or
556characteristics of the Perl 5 object system, only to create a
27e31eaf 557protocol for its manipulation and introspection.
94b19069 558
1d68af04 559That said, it does attempt to create the tools for building a rich
560set of extensions to the Perl 5 object system. Every attempt has been
561made for these tools to keep to the spirit of the Perl 5 object
94b19069 562system that we all know and love.
563
1d68af04 564This documentation is admittedly sparse on details, as time permits
565I will try to improve them. For now, I suggest looking at the items
566listed in the L<SEE ALSO> section for more information. In particular
567the book "The Art of the Meta Object Protocol" was very influential
40483095 568in the development of this system.
569
bfe4d0fc 570=head2 What is a Meta Object Protocol?
571
1d68af04 572A meta object protocol is an API to an object system.
bfe4d0fc 573
1d68af04 574To be more specific, it is a set of abstractions of the components of
575an object system (typically things like; classes, object, methods,
576object attributes, etc.). These abstractions can then be used to both
bfe4d0fc 577inspect and manipulate the object system which they describe.
578
1d68af04 579It can be said that there are two MOPs for any object system; the
580implicit MOP, and the explicit MOP. The implicit MOP handles things
581like method dispatch or inheritance, which happen automatically as
582part of how the object system works. The explicit MOP typically
583handles the introspection/reflection features of the object system.
584All object systems have implicit MOPs, without one, they would not
585work. Explict MOPs however as less common, and depending on the
586language can vary from restrictive (Reflection in Java or C#) to
587wide open (CLOS is a perfect example).
bfe4d0fc 588
e16da3e6 589=head2 Yet Another Class Builder!! Why?
590
1d68af04 591This is B<not> a class builder so much as it is a I<class builder
592B<builder>>. My intent is that an end user does not use this module
593directly, but instead this module is used by module authors to
594build extensions and features onto the Perl 5 object system.
e16da3e6 595
94b19069 596=head2 Who is this module for?
597
1d68af04 598This module is specifically for anyone who has ever created or
599wanted to create a module for the Class:: namespace. The tools which
600this module will provide will hopefully make it easier to do more
601complex things with Perl 5 classes by removing such barriers as
602the need to hack the symbol tables, or understand the fine details
603of method dispatch.
94b19069 604
bfe4d0fc 605=head2 What changes do I have to make to use this module?
606
1d68af04 607This module was designed to be as unintrusive as possible. Many of
608its features are accessible without B<any> change to your existsing
609code at all. It is meant to be a compliment to your existing code and
610not an intrusion on your code base. Unlike many other B<Class::>
611modules, this module B<does not> require you subclass it, or even that
612you C<use> it in within your module's package.
bfe4d0fc 613
1d68af04 614The only features which requires additions to your code are the
2eb717d5 615attribute handling and instance construction features, and these are
1d68af04 616both completely optional features. The only reason for this is because
617Perl 5's object system does not actually have these features built
2eb717d5 618in. More information about this feature can be found below.
bfe4d0fc 619
620=head2 A Note about Performance?
621
1d68af04 622It is a common misconception that explict MOPs are performance drains.
623But this is not a universal truth at all, it is an side-effect of
624specific implementations. For instance, using Java reflection is much
625slower because the JVM cannot take advantage of any compiler
626optimizations, and the JVM has to deal with much more runtime type
627information as well. Reflection in C# is marginally better as it was
628designed into the language and runtime (the CLR). In contrast, CLOS
629(the Common Lisp Object System) was built to support an explicit MOP,
630and so performance is tuned for it.
631
632This library in particular does it's absolute best to avoid putting
633B<any> drain at all upon your code's performance. In fact, by itself
634it does nothing to affect your existing code. So you only pay for
2eb717d5 635what you actually use.
bfe4d0fc 636
550d56db 637=head2 About Metaclass compatibility
638
1d68af04 639This module makes sure that all metaclasses created are both upwards
640and downwards compatible. The topic of metaclass compatibility is
641highly esoteric and is something only encountered when doing deep and
642involved metaclass hacking. There are two basic kinds of metaclass
643incompatibility; upwards and downwards.
550d56db 644
1d68af04 645Upwards metaclass compatibility means that the metaclass of a
646given class is either the same as (or a subclass of) all of the
550d56db 647class's ancestors.
648
1d68af04 649Downward metaclass compatibility means that the metaclasses of a
650given class's anscestors are all either the same as (or a subclass
550d56db 651of) that metaclass.
652
1d68af04 653Here is a diagram showing a set of two classes (C<A> and C<B>) and
654two metaclasses (C<Meta::A> and C<Meta::B>) which have correct
550d56db 655metaclass compatibility both upwards and downwards.
656
657 +---------+ +---------+
658 | Meta::A |<----| Meta::B | <....... (instance of )
1d68af04 659 +---------+ +---------+ <------- (inherits from)
550d56db 660 ^ ^
661 : :
662 +---------+ +---------+
663 | A |<----| B |
664 +---------+ +---------+
665
1d68af04 666As I said this is a highly esoteric topic and one you will only run
667into if you do a lot of subclassing of B<Class::MOP::Class>. If you
668are interested in why this is an issue see the paper
669I<Uniform and safe metaclass composition> linked to in the
550d56db 670L<SEE ALSO> section of this document.
671
aa448b16 672=head2 Using custom metaclasses
673
1d68af04 674Always use the metaclass pragma when using a custom metaclass, this
675will ensure the proper initialization order and not accidentely
676create an incorrect type of metaclass for you. This is a very rare
677problem, and one which can only occur if you are doing deep metaclass
aa448b16 678programming. So in other words, don't worry about it.
679
94b19069 680=head1 PROTOCOLS
681
682The protocol is divided into 3 main sub-protocols:
683
684=over 4
685
686=item The Class protocol
687
1d68af04 688This provides a means of manipulating and introspecting a Perl 5
689class. It handles all of symbol table hacking for you, and provides
94b19069 690a rich set of methods that go beyond simple package introspection.
691
552e3d24 692See L<Class::MOP::Class> for more details.
693
94b19069 694=item The Attribute protocol
695
1d68af04 696This provides a consistent represenation for an attribute of a
697Perl 5 class. Since there are so many ways to create and handle
698atttributes in Perl 5 OO, this attempts to provide as much of a
699unified approach as possible, while giving the freedom and
94b19069 700flexibility to subclass for specialization.
701
552e3d24 702See L<Class::MOP::Attribute> for more details.
703
94b19069 704=item The Method protocol
705
1d68af04 706This provides a means of manipulating and introspecting methods in
707the Perl 5 object system. As with attributes, there are many ways to
708approach this topic, so we try to keep it pretty basic, while still
94b19069 709making it possible to extend the system in many ways.
710
552e3d24 711See L<Class::MOP::Method> for more details.
94b19069 712
713=back
714
be7677c7 715=head1 FUNCTIONS
716
448b6e55 717=head2 Utility functions
718
719=over 4
720
721=item B<load_class ($class_name)>
722
1d68af04 723This will load a given C<$class_name> and if it does not have an
448b6e55 724already initialized metaclass, then it will intialize one for it.
725
726=item B<is_class_loaded ($class_name)>
727
1d68af04 728This will return a boolean depending on if the C<$class_name> has
729been loaded.
448b6e55 730
1d68af04 731NOTE: This does a basic check of the symbol table to try and
448b6e55 732determine as best it can if the C<$class_name> is loaded, it
1d68af04 733is probably correct about 99% of the time.
448b6e55 734
735=back
736
737=head2 Metaclass cache functions
738
1d68af04 739Class::MOP holds a cache of metaclasses, the following are functions
740(B<not methods>) which can be used to access that cache. It is not
741recommended that you mess with this, bad things could happen. But if
be7677c7 742you are brave and willing to risk it, go for it.
743
744=over 4
745
746=item B<get_all_metaclasses>
747
1d68af04 748This will return an hash of all the metaclass instances that have
749been cached by B<Class::MOP::Class> keyed by the package name.
b9d9fc0b 750
be7677c7 751=item B<get_all_metaclass_instances>
752
1d68af04 753This will return an array of all the metaclass instances that have
b9d9fc0b 754been cached by B<Class::MOP::Class>.
755
be7677c7 756=item B<get_all_metaclass_names>
757
1d68af04 758This will return an array of all the metaclass names that have
b9d9fc0b 759been cached by B<Class::MOP::Class>.
760
be7677c7 761=item B<get_metaclass_by_name ($name)>
762
763=item B<store_metaclass_by_name ($name, $meta)>
764
765=item B<weaken_metaclass ($name)>
766
767=item B<does_metaclass_exist ($name)>
768
769=item B<remove_metaclass_by_name ($name)>
770
771=back
772
552e3d24 773=head1 SEE ALSO
8b978dd5 774
552e3d24 775=head2 Books
8b978dd5 776
1d68af04 777There are very few books out on Meta Object Protocols and Metaclasses
778because it is such an esoteric topic. The following books are really
779the only ones I have found. If you know of any more, B<I<please>>
a2e85e6c 780email me and let me know, I would love to hear about them.
781
8b978dd5 782=over 4
783
552e3d24 784=item "The Art of the Meta Object Protocol"
8b978dd5 785
552e3d24 786=item "Advances in Object-Oriented Metalevel Architecture and Reflection"
8b978dd5 787
b51af7f9 788=item "Putting MetaClasses to Work"
789
a2e85e6c 790=item "Smalltalk: The Language"
791
94b19069 792=back
793
550d56db 794=head2 Papers
795
796=over 4
797
798=item Uniform and safe metaclass composition
799
1d68af04 800An excellent paper by the people who brought us the original Traits paper.
801This paper is on how Traits can be used to do safe metaclass composition,
802and offers an excellent introduction section which delves into the topic of
550d56db 803metaclass compatibility.
804
805L<http://www.iam.unibe.ch/~scg/Archive/Papers/Duca05ySafeMetaclassTrait.pdf>
806
807=item Safe Metaclass Programming
808
1d68af04 809This paper seems to precede the above paper, and propose a mix-in based
810approach as opposed to the Traits based approach. Both papers have similar
811information on the metaclass compatibility problem space.
550d56db 812
813L<http://citeseer.ist.psu.edu/37617.html>
814
815=back
816
552e3d24 817=head2 Prior Art
8b978dd5 818
819=over 4
820
7184ca14 821=item The Perl 6 MetaModel work in the Pugs project
8b978dd5 822
823=over 4
824
552e3d24 825=item L<http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel>
8b978dd5 826
552e3d24 827=item L<http://svn.openfoundry.org/pugs/perl5/Perl6-ObjectSpace>
8b978dd5 828
829=back
830
94b19069 831=back
832
1d68af04 833=head2 Articles
f8dfcfb7 834
835=over 4
836
1d68af04 837=item CPAN Module Review of Class::MOP
f8dfcfb7 838
839L<http://www.oreillynet.com/onlamp/blog/2006/06/cpan_module_review_classmop.html>
840
841=back
842
a2e85e6c 843=head1 SIMILAR MODULES
844
1d68af04 845As I have said above, this module is a class-builder-builder, so it is
846not the same thing as modules like L<Class::Accessor> and
847L<Class::MethodMaker>. That being said there are very few modules on CPAN
848with similar goals to this module. The one I have found which is most
849like this module is L<Class::Meta>, although it's philosophy and the MOP it
850creates are very different from this modules.
94b19069 851
a2e85e6c 852=head1 BUGS
853
1d68af04 854All complex software has bugs lurking in it, and this module is no
a2e85e6c 855exception. If you find a bug please either email me, or add the bug
856to cpan-RT.
857
858=head1 ACKNOWLEDGEMENTS
859
860=over 4
861
b9d9fc0b 862=item Rob Kinyon
a2e85e6c 863
1d68af04 864Thanks to Rob for actually getting the development of this module kick-started.
a2e85e6c 865
866=back
867
1a09d9cc 868=head1 AUTHORS
94b19069 869
a2e85e6c 870Stevan Little E<lt>stevan@iinteractive.comE<gt>
552e3d24 871
9c8cda90 872B<with contributions from:>
873
874Brandon (blblack) Black
875
876Guillermo (groditi) Roditi
877
9195ddff 878Matt (mst) Trout
879
9c8cda90 880Rob (robkinyon) Kinyon
881
882Yuval (nothingmuch) Kogman
1a09d9cc 883
94b19069 884=head1 COPYRIGHT AND LICENSE
885
2367814a 886Copyright 2006, 2007 by Infinity Interactive, Inc.
94b19069 887
888L<http://www.iinteractive.com>
889
890This library is free software; you can redistribute it and/or modify
1d68af04 891it under the same terms as Perl itself.
94b19069 892
893=cut