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