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