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