tweaking the attribute initializer stuff a little
[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(
0ab65f99 340 Class::MOP::Attribute->new('$!initializer' => (
341 init_arg => 'initializer',
8ee74136 342 reader => { 'initializer' => \&Class::MOP::Attribute::initializer },
343 predicate => { 'has_initializer' => \&Class::MOP::Attribute::has_initializer },
0ab65f99 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