More refactoring of immutable code to make it easy to integrate
[gitmo/Class-MOP.git] / lib / Class / MOP / Class.pm
1
2 package Class::MOP::Class;
3
4 use strict;
5 use warnings;
6
7 use Class::MOP::Immutable;
8 use Class::MOP::Instance;
9 use Class::MOP::Method::Wrapped;
10
11 use Carp         'confess';
12 use Scalar::Util 'blessed', 'weaken';
13
14 our $VERSION   = '0.78';
15 $VERSION = eval $VERSION;
16 our $AUTHORITY = 'cpan:STEVAN';
17
18 use base 'Class::MOP::Module';
19
20 # Creation
21
22 sub initialize {
23     my $class = shift;
24
25     my $package_name;
26     
27     if ( @_ % 2 ) {
28         $package_name = shift;
29     } else {
30         my %options = @_;
31         $package_name = $options{package};
32     }
33
34     (defined $package_name && $package_name && !ref($package_name))
35         || confess "You must pass a package name and it cannot be blessed";
36
37     return Class::MOP::get_metaclass_by_name($package_name)
38         || $class->construct_class_instance(package => $package_name, @_);
39 }
40
41 # NOTE: (meta-circularity)
42 # this is a special form of &construct_instance
43 # (see below), which is used to construct class
44 # meta-object instances for any Class::MOP::*
45 # class. All other classes will use the more
46 # normal &construct_instance.
47 sub construct_class_instance {
48     my $class        = shift;
49     my $options      = @_ == 1 ? $_[0] : {@_};
50     my $package_name = $options->{package};
51     (defined $package_name && $package_name)
52         || confess "You must pass a package name";
53     # NOTE:
54     # return the metaclass if we have it cached,
55     # and it is still defined (it has not been
56     # reaped by DESTROY yet, which can happen
57     # annoyingly enough during global destruction)
58
59     if (defined(my $meta = Class::MOP::get_metaclass_by_name($package_name))) {
60         return $meta;
61     }
62
63     # NOTE:
64     # we need to deal with the possibility
65     # of class immutability here, and then
66     # get the name of the class appropriately
67     $class = (ref($class)
68                     ? ($class->is_immutable
69                         ? $class->get_mutable_metaclass_name()
70                         : ref($class))
71                     : $class);
72
73     # now create the metaclass
74     my $meta;
75     if ($class eq 'Class::MOP::Class') {
76         $meta = $class->_new($options);
77     }
78     else {
79         # NOTE:
80         # it is safe to use meta here because
81         # class will always be a subclass of
82         # Class::MOP::Class, which defines meta
83         $meta = $class->meta->construct_instance($options)
84     }
85
86     # and check the metaclass compatibility
87     $meta->check_metaclass_compatibility();  
88
89     Class::MOP::store_metaclass_by_name($package_name, $meta);
90
91     # NOTE:
92     # we need to weaken any anon classes
93     # so that they can call DESTROY properly
94     Class::MOP::weaken_metaclass($package_name) if $meta->is_anon_class;
95
96     $meta;
97 }
98
99 sub _new {
100     my $class = shift;
101     my $options = @_ == 1 ? $_[0] : {@_};
102
103     bless {
104         # inherited from Class::MOP::Package
105         'package' => $options->{package},
106
107         # NOTE:
108         # since the following attributes will
109         # actually be loaded from the symbol
110         # table, and actually bypass the instance
111         # entirely, we can just leave these things
112         # listed here for reference, because they
113         # should not actually have a value associated
114         # with the slot.
115         'namespace' => \undef,
116
117         # inherited from Class::MOP::Module
118         'version'   => \undef,
119         'authority' => \undef,
120
121         # defined in Class::MOP::Class
122         'superclasses' => \undef,
123
124         'methods'             => {},
125         'attributes'          => {},
126         'attribute_metaclass' => $options->{'attribute_metaclass'}
127             || 'Class::MOP::Attribute',
128         'method_metaclass' => $options->{'method_metaclass'}
129             || 'Class::MOP::Method',
130         'wrapped_method_metaclass' => $options->{'wrapped_method_metaclass'}
131             || 'Class::MOP::Method::Wrapped',
132         'instance_metaclass' => $options->{'instance_metaclass'}
133             || 'Class::MOP::Instance',
134     }, $class;
135 }
136
137 sub reset_package_cache_flag  { (shift)->{'_package_cache_flag'} = undef } 
138 sub update_package_cache_flag {
139     my $self = shift;
140     # NOTE:
141     # we can manually update the cache number 
142     # since we are actually adding the method
143     # to our cache as well. This avoids us 
144     # having to regenerate the method_map.
145     # - SL    
146     $self->{'_package_cache_flag'} = Class::MOP::check_package_cache_flag($self->name);    
147 }
148
149 sub check_metaclass_compatibility {
150     my $self = shift;
151
152     # this is always okay ...
153     return if ref($self)                eq 'Class::MOP::Class'   &&
154               $self->instance_metaclass eq 'Class::MOP::Instance';
155
156     my @class_list = $self->linearized_isa;
157     shift @class_list; # shift off $self->name
158
159     foreach my $superclass_name (@class_list) {
160         my $super_meta = Class::MOP::get_metaclass_by_name($superclass_name) || next;
161
162         # NOTE:
163         # we need to deal with the possibility
164         # of class immutability here, and then
165         # get the name of the class appropriately
166         my $super_meta_type
167             = $super_meta->is_immutable
168             ? $super_meta->get_mutable_metaclass_name()
169             : ref($super_meta);
170
171         ($self->isa($super_meta_type))
172             || confess $self->name . "->meta => (" . (ref($self)) . ")" .
173                        " is not compatible with the " .
174                        $superclass_name . "->meta => (" . ($super_meta_type)     . ")";
175         # NOTE:
176         # we also need to check that instance metaclasses
177         # are compatibile in the same the class.
178         ($self->instance_metaclass->isa($super_meta->instance_metaclass))
179             || confess $self->name . "->meta->instance_metaclass => (" . ($self->instance_metaclass) . ")" .
180                        " is not compatible with the " .
181                        $superclass_name . "->meta->instance_metaclass => (" . ($super_meta->instance_metaclass) . ")";
182     }
183 }
184
185 ## ANON classes
186
187 {
188     # NOTE:
189     # this should be sufficient, if you have a
190     # use case where it is not, write a test and
191     # I will change it.
192     my $ANON_CLASS_SERIAL = 0;
193
194     # NOTE:
195     # we need a sufficiently annoying prefix
196     # this should suffice for now, this is
197     # used in a couple of places below, so
198     # need to put it up here for now.
199     my $ANON_CLASS_PREFIX = 'Class::MOP::Class::__ANON__::SERIAL::';
200
201     sub is_anon_class {
202         my $self = shift;
203         no warnings 'uninitialized';
204         $self->name =~ /^$ANON_CLASS_PREFIX/;
205     }
206
207     sub create_anon_class {
208         my ($class, %options) = @_;
209         my $package_name = $ANON_CLASS_PREFIX . ++$ANON_CLASS_SERIAL;
210         return $class->create($package_name, %options);
211     }
212
213     # NOTE:
214     # this will only get called for
215     # anon-classes, all other calls
216     # are assumed to occur during
217     # global destruction and so don't
218     # really need to be handled explicitly
219     sub DESTROY {
220         my $self = shift;
221
222         return if Class::MOP::in_global_destruction(); # it'll happen soon anyway and this just makes things more complicated
223
224         no warnings 'uninitialized';
225         return unless $self->name =~ /^$ANON_CLASS_PREFIX/;
226         # Moose does a weird thing where it replaces the metaclass for
227         # class when fixing metaclass incompatibility. In that case,
228         # we don't want to clean out the namespace now. We can detect
229         # that because Moose will explicitly update the singleton
230         # cache in Class::MOP.
231         my $current_meta = Class::MOP::get_metaclass_by_name($self->name);
232         return if $current_meta ne $self;
233
234         my ($serial_id) = ($self->name =~ /^$ANON_CLASS_PREFIX(\d+)/);
235         no strict 'refs';
236         foreach my $key (keys %{$ANON_CLASS_PREFIX . $serial_id}) {
237             delete ${$ANON_CLASS_PREFIX . $serial_id}{$key};
238         }
239         delete ${'main::' . $ANON_CLASS_PREFIX}{$serial_id . '::'};
240     }
241
242 }
243
244 # creating classes with MOP ...
245
246 sub create {
247     my ( $class, @args ) = @_;
248
249     unshift @args, 'package' if @args % 2 == 1;
250
251     my (%options) = @args;
252     my $package_name = $options{package};
253
254     (ref $options{superclasses} eq 'ARRAY')
255         || confess "You must pass an ARRAY ref of superclasses"
256             if exists $options{superclasses};
257             
258     (ref $options{attributes} eq 'ARRAY')
259         || confess "You must pass an ARRAY ref of attributes"
260             if exists $options{attributes};      
261             
262     (ref $options{methods} eq 'HASH')
263         || confess "You must pass a HASH ref of methods"
264             if exists $options{methods};                  
265
266     $class->SUPER::create(%options);
267
268     my (%initialize_options) = @args;
269     delete @initialize_options{qw(
270         package
271         superclasses
272         attributes
273         methods
274         version
275         authority
276     )};
277     my $meta = $class->initialize( $package_name => %initialize_options );
278
279     # FIXME totally lame
280     $meta->add_method('meta' => sub {
281         $class->initialize(ref($_[0]) || $_[0]);
282     });
283
284     $meta->superclasses(@{$options{superclasses}})
285         if exists $options{superclasses};
286     # NOTE:
287     # process attributes first, so that they can
288     # install accessors, but locally defined methods
289     # can then overwrite them. It is maybe a little odd, but
290     # I think this should be the order of things.
291     if (exists $options{attributes}) {
292         foreach my $attr (@{$options{attributes}}) {
293             $meta->add_attribute($attr);
294         }
295     }
296     if (exists $options{methods}) {
297         foreach my $method_name (keys %{$options{methods}}) {
298             $meta->add_method($method_name, $options{methods}->{$method_name});
299         }
300     }
301     return $meta;
302 }
303
304 ## Attribute readers
305
306 # NOTE:
307 # all these attribute readers will be bootstrapped
308 # away in the Class::MOP bootstrap section
309
310 sub get_attribute_map        { $_[0]->{'attributes'}                  }
311 sub attribute_metaclass      { $_[0]->{'attribute_metaclass'}         }
312 sub method_metaclass         { $_[0]->{'method_metaclass'}            }
313 sub wrapped_method_metaclass { $_[0]->{'wrapped_method_metaclass'}    }
314 sub instance_metaclass       { $_[0]->{'instance_metaclass'}          }
315
316 # Instance Construction & Cloning
317
318 sub new_object {
319     my $class = shift;
320
321     # NOTE:
322     # we need to protect the integrity of the
323     # Class::MOP::Class singletons here, so we
324     # delegate this to &construct_class_instance
325     # which will deal with the singletons
326     return $class->construct_class_instance(@_)
327         if $class->name->isa('Class::MOP::Class');
328     return $class->construct_instance(@_);
329 }
330
331 sub construct_instance {
332     my $class = shift;
333     my $params = @_ == 1 ? $_[0] : {@_};
334     my $meta_instance = $class->get_meta_instance();
335     my $instance = $meta_instance->create_instance();
336     foreach my $attr ($class->compute_all_applicable_attributes()) {
337         $attr->initialize_instance_slot($meta_instance, $instance, $params);
338     }
339     # NOTE:
340     # this will only work for a HASH instance type
341     if ($class->is_anon_class) {
342         (Scalar::Util::reftype($instance) eq 'HASH')
343             || confess "Currently only HASH based instances are supported with instance of anon-classes";
344         # NOTE:
345         # At some point we should make this official
346         # as a reserved slot name, but right now I am
347         # going to keep it here.
348         # my $RESERVED_MOP_SLOT = '__MOP__';
349         $instance->{'__MOP__'} = $class;
350     }
351     return $instance;
352 }
353
354
355 sub get_meta_instance {
356     my $self = shift;
357     $self->{'_meta_instance'} ||= $self->create_meta_instance();
358 }
359
360 sub create_meta_instance {
361     my $self = shift;
362     
363     my $instance = $self->instance_metaclass->new(
364         associated_metaclass => $self,
365         attributes => [ $self->compute_all_applicable_attributes() ],
366     );
367
368     $self->add_meta_instance_dependencies()
369         if $instance->is_dependent_on_superclasses();
370
371     return $instance;
372 }
373
374 sub clone_object {
375     my $class    = shift;
376     my $instance = shift;
377     (blessed($instance) && $instance->isa($class->name))
378         || confess "You must pass an instance of the metaclass (" . (ref $class ? $class->name : $class) . "), not ($instance)";
379
380     # NOTE:
381     # we need to protect the integrity of the
382     # Class::MOP::Class singletons here, they
383     # should not be cloned.
384     return $instance if $instance->isa('Class::MOP::Class');
385     $class->clone_instance($instance, @_);
386 }
387
388 sub clone_instance {
389     my ($class, $instance, %params) = @_;
390     (blessed($instance))
391         || confess "You can only clone instances, ($instance) is not a blessed instance";
392     my $meta_instance = $class->get_meta_instance();
393     my $clone = $meta_instance->clone_instance($instance);
394     foreach my $attr ($class->compute_all_applicable_attributes()) {
395         if ( defined( my $init_arg = $attr->init_arg ) ) {
396             if (exists $params{$init_arg}) {
397                 $attr->set_value($clone, $params{$init_arg});
398             }
399         }
400     }
401     return $clone;
402 }
403
404 sub rebless_instance {
405     my ($self, $instance, %params) = @_;
406
407     my $old_metaclass;
408     if ($instance->can('meta')) {
409         ($instance->meta->isa('Class::MOP::Class'))
410             || confess 'Cannot rebless instance if ->meta is not an instance of Class::MOP::Class';
411         $old_metaclass = $instance->meta;
412     }
413     else {
414         $old_metaclass = $self->initialize(ref($instance));
415     }
416
417     my $meta_instance = $self->get_meta_instance();
418
419     $self->name->isa($old_metaclass->name)
420         || confess "You may rebless only into a subclass of (". $old_metaclass->name ."), of which (". $self->name .") isn't.";
421
422     # rebless!
423     # we use $_[1] here because of t/306_rebless_overload.t regressions on 5.8.8
424     $meta_instance->rebless_instance_structure($_[1], $self);
425
426     foreach my $attr ( $self->compute_all_applicable_attributes ) {
427         if ( $attr->has_value($instance) ) {
428             if ( defined( my $init_arg = $attr->init_arg ) ) {
429                 $params{$init_arg} = $attr->get_value($instance)
430                     unless exists $params{$init_arg};
431             } 
432             else {
433                 $attr->set_value($instance, $attr->get_value($instance));
434             }
435         }
436     }
437
438     foreach my $attr ($self->compute_all_applicable_attributes) {
439         $attr->initialize_instance_slot($meta_instance, $instance, \%params);
440     }
441     
442     $instance;
443 }
444
445 # Inheritance
446
447 sub superclasses {
448     my $self     = shift;
449     my $var_spec = { sigil => '@', type => 'ARRAY', name => 'ISA' };
450     if (@_) {
451         my @supers = @_;
452         @{$self->get_package_symbol($var_spec)} = @supers;
453
454         # NOTE:
455         # on 5.8 and below, we need to call
456         # a method to get Perl to detect
457         # a cycle in the class hierarchy
458         my $class = $self->name;
459         $class->isa($class);
460
461         # NOTE:
462         # we need to check the metaclass
463         # compatibility here so that we can
464         # be sure that the superclass is
465         # not potentially creating an issues
466         # we don't know about
467
468         $self->check_metaclass_compatibility();
469         $self->update_meta_instance_dependencies();
470     }
471     @{$self->get_package_symbol($var_spec)};
472 }
473
474 sub subclasses {
475     my $self = shift;
476
477     my $super_class = $self->name;
478
479     if ( Class::MOP::HAVE_ISAREV() ) {
480         return @{ $super_class->mro::get_isarev() };
481     } else {
482         my @derived_classes;
483
484         my $find_derived_classes;
485         $find_derived_classes = sub {
486             my ($outer_class) = @_;
487
488             my $symbol_table_hashref = do { no strict 'refs'; \%{"${outer_class}::"} };
489
490             SYMBOL:
491             for my $symbol ( keys %$symbol_table_hashref ) {
492                 next SYMBOL if $symbol !~ /\A (\w+):: \z/x;
493                 my $inner_class = $1;
494
495                 next SYMBOL if $inner_class eq 'SUPER';    # skip '*::SUPER'
496
497                 my $class =
498                 $outer_class
499                 ? "${outer_class}::$inner_class"
500                 : $inner_class;
501
502                 if ( $class->isa($super_class) and $class ne $super_class ) {
503                     push @derived_classes, $class;
504                 }
505
506                 next SYMBOL if $class eq 'main';           # skip 'main::*'
507
508                 $find_derived_classes->($class);
509             }
510         };
511
512         my $root_class = q{};
513         $find_derived_classes->($root_class);
514
515         undef $find_derived_classes;
516
517         @derived_classes = sort { $a->isa($b) ? 1 : $b->isa($a) ? -1 : 0 } @derived_classes;
518
519         return @derived_classes;
520     }
521 }
522
523
524 sub linearized_isa {
525     return @{ mro::get_linear_isa( (shift)->name ) };
526 }
527
528 sub class_precedence_list {
529     my $self = shift;
530     my $name = $self->name;
531
532     unless (Class::MOP::IS_RUNNING_ON_5_10()) { 
533         # NOTE:
534         # We need to check for circular inheritance here
535         # if we are are not on 5.10, cause 5.8 detects it 
536         # late. This will do nothing if all is well, and 
537         # blow up otherwise. Yes, it's an ugly hack, better
538         # suggestions are welcome.        
539         # - SL
540         ($name || return)->isa('This is a test for circular inheritance') 
541     }
542
543     # if our mro is c3, we can 
544     # just grab the linear_isa
545     if (mro::get_mro($name) eq 'c3') {
546         return @{ mro::get_linear_isa($name) }
547     }
548     else {
549         # NOTE:
550         # we can't grab the linear_isa for dfs
551         # since it has all the duplicates 
552         # already removed.
553         return (
554             $name,
555             map {
556                 $self->initialize($_)->class_precedence_list()
557             } $self->superclasses()
558         );
559     }
560 }
561
562 ## Methods
563
564 sub wrap_method_body {
565     my ( $self, %args ) = @_;
566
567     ('CODE' eq ref $args{body})
568         || confess "Your code block must be a CODE reference";
569
570     $self->method_metaclass->wrap(
571         package_name => $self->name,
572         %args,
573     );
574 }
575
576 sub add_method {
577     my ($self, $method_name, $method) = @_;
578     (defined $method_name && $method_name)
579         || confess "You must define a method name";
580
581     my $body;
582     if (blessed($method)) {
583         $body = $method->body;
584         if ($method->package_name ne $self->name) {
585             $method = $method->clone(
586                 package_name => $self->name,
587                 name         => $method_name            
588             ) if $method->can('clone');
589         }
590     }
591     else {
592         $body = $method;
593         $method = $self->wrap_method_body( body => $body, name => $method_name );
594     }
595
596     $method->attach_to_class($self);
597
598     # This used to call get_method_map, which meant we would build all
599     # the method objects for the class just because we added one
600     # method. This is hackier, but quicker too.
601     $self->{methods}{$method_name} = $method;
602     
603     my $full_method_name = ($self->name . '::' . $method_name);    
604     $self->add_package_symbol(
605         { sigil => '&', type => 'CODE', name => $method_name }, 
606         Class::MOP::subname($full_method_name => $body)
607     );
608 }
609
610 {
611     my $fetch_and_prepare_method = sub {
612         my ($self, $method_name) = @_;
613         my $wrapped_metaclass = $self->wrapped_method_metaclass;
614         # fetch it locally
615         my $method = $self->get_method($method_name);
616         # if we dont have local ...
617         unless ($method) {
618             # try to find the next method
619             $method = $self->find_next_method_by_name($method_name);
620             # die if it does not exist
621             (defined $method)
622                 || confess "The method '$method_name' was not found in the inheritance hierarchy for " . $self->name;
623             # and now make sure to wrap it
624             # even if it is already wrapped
625             # because we need a new sub ref
626             $method = $wrapped_metaclass->wrap($method);
627         }
628         else {
629             # now make sure we wrap it properly
630             $method = $wrapped_metaclass->wrap($method)
631                 unless $method->isa($wrapped_metaclass);
632         }
633         $self->add_method($method_name => $method);
634         return $method;
635     };
636
637     sub add_before_method_modifier {
638         my ($self, $method_name, $method_modifier) = @_;
639         (defined $method_name && $method_name)
640             || confess "You must pass in a method name";
641         my $method = $fetch_and_prepare_method->($self, $method_name);
642         $method->add_before_modifier(
643             Class::MOP::subname(':before' => $method_modifier)
644         );
645     }
646
647     sub add_after_method_modifier {
648         my ($self, $method_name, $method_modifier) = @_;
649         (defined $method_name && $method_name)
650             || confess "You must pass in a method name";
651         my $method = $fetch_and_prepare_method->($self, $method_name);
652         $method->add_after_modifier(
653             Class::MOP::subname(':after' => $method_modifier)
654         );
655     }
656
657     sub add_around_method_modifier {
658         my ($self, $method_name, $method_modifier) = @_;
659         (defined $method_name && $method_name)
660             || confess "You must pass in a method name";
661         my $method = $fetch_and_prepare_method->($self, $method_name);
662         $method->add_around_modifier(
663             Class::MOP::subname(':around' => $method_modifier)
664         );
665     }
666
667     # NOTE:
668     # the methods above used to be named like this:
669     #    ${pkg}::${method}:(before|after|around)
670     # but this proved problematic when using one modifier
671     # to wrap multiple methods (something which is likely
672     # to happen pretty regularly IMO). So instead of naming
673     # it like this, I have chosen to just name them purely
674     # with their modifier names, like so:
675     #    :(before|after|around)
676     # The fact is that in a stack trace, it will be fairly
677     # evident from the context what method they are attached
678     # to, and so don't need the fully qualified name.
679 }
680
681 sub alias_method {
682     my $self = shift;
683
684     $self->add_method(@_);
685 }
686
687 sub has_method {
688     my ($self, $method_name) = @_;
689     (defined $method_name && $method_name)
690         || confess "You must define a method name";
691
692     exists $self->{methods}{$method_name} || exists $self->get_method_map->{$method_name};
693 }
694
695 sub get_method {
696     my ($self, $method_name) = @_;
697     (defined $method_name && $method_name)
698         || confess "You must define a method name";
699
700     return $self->{methods}{$method_name} || $self->get_method_map->{$method_name};
701 }
702
703 sub remove_method {
704     my ($self, $method_name) = @_;
705     (defined $method_name && $method_name)
706         || confess "You must define a method name";
707
708     my $removed_method = delete $self->get_method_map->{$method_name};
709     
710     $self->remove_package_symbol(
711         { sigil => '&', type => 'CODE', name => $method_name }
712     );
713
714     $removed_method->detach_from_class if $removed_method;
715
716     $self->update_package_cache_flag; # still valid, since we just removed the method from the map
717
718     return $removed_method;
719 }
720
721 sub get_method_list {
722     my $self = shift;
723     keys %{$self->get_method_map};
724 }
725
726 sub find_method_by_name {
727     my ($self, $method_name) = @_;
728     (defined $method_name && $method_name)
729         || confess "You must define a method name to find";
730     foreach my $class ($self->linearized_isa) {
731         # fetch the meta-class ...
732         my $meta = $self->initialize($class);
733         return $meta->get_method($method_name)
734             if $meta->has_method($method_name);
735     }
736     return;
737 }
738
739 sub get_all_methods {
740     my $self = shift;
741     my %methods = map { %{ $self->initialize($_)->get_method_map } } reverse $self->linearized_isa;
742     return values %methods;
743 }
744
745 # compatibility
746 sub compute_all_applicable_methods {
747     return map {
748         {
749             name  => $_->name,
750             class => $_->package_name,
751             code  => $_, # sigh, overloading
752         },
753     } shift->get_all_methods(@_);
754 }
755
756 sub get_all_method_names {
757     my $self = shift;
758     my %uniq;
759     grep { $uniq{$_}++ == 0 } map { $_->name } $self->get_all_methods;
760 }
761
762 sub find_all_methods_by_name {
763     my ($self, $method_name) = @_;
764     (defined $method_name && $method_name)
765         || confess "You must define a method name to find";
766     my @methods;
767     foreach my $class ($self->linearized_isa) {
768         # fetch the meta-class ...
769         my $meta = $self->initialize($class);
770         push @methods => {
771             name  => $method_name,
772             class => $class,
773             code  => $meta->get_method($method_name)
774         } if $meta->has_method($method_name);
775     }
776     return @methods;
777 }
778
779 sub find_next_method_by_name {
780     my ($self, $method_name) = @_;
781     (defined $method_name && $method_name)
782         || confess "You must define a method name to find";
783     my @cpl = $self->linearized_isa;
784     shift @cpl; # discard ourselves
785     foreach my $class (@cpl) {
786         # fetch the meta-class ...
787         my $meta = $self->initialize($class);
788         return $meta->get_method($method_name)
789             if $meta->has_method($method_name);
790     }
791     return;
792 }
793
794 ## Attributes
795
796 sub add_attribute {
797     my $self      = shift;
798     # either we have an attribute object already
799     # or we need to create one from the args provided
800     my $attribute = blessed($_[0]) ? $_[0] : $self->attribute_metaclass->new(@_);
801     # make sure it is derived from the correct type though
802     ($attribute->isa('Class::MOP::Attribute'))
803         || confess "Your attribute must be an instance of Class::MOP::Attribute (or a subclass)";
804
805     # first we attach our new attribute
806     # because it might need certain information
807     # about the class which it is attached to
808     $attribute->attach_to_class($self);
809
810     # then we remove attributes of a conflicting
811     # name here so that we can properly detach
812     # the old attr object, and remove any
813     # accessors it would have generated
814     if ( $self->has_attribute($attribute->name) ) {
815         $self->remove_attribute($attribute->name);
816     } else {
817         $self->invalidate_meta_instances();
818     }
819
820     # then onto installing the new accessors
821     $self->get_attribute_map->{$attribute->name} = $attribute;
822
823     # invalidate package flag here
824     my $e = do { local $@; eval { $attribute->install_accessors() }; $@ };
825     if ( $e ) {
826         $self->remove_attribute($attribute->name);
827         die $e;
828     }
829
830     return $attribute;
831 }
832
833 sub update_meta_instance_dependencies {
834     my $self = shift;
835
836     if ( $self->{meta_instance_dependencies} ) {
837         return $self->add_meta_instance_dependencies;
838     }
839 }
840
841 sub add_meta_instance_dependencies {
842     my $self = shift;
843
844     $self->remove_meta_instance_dependencies;
845
846     my @attrs = $self->compute_all_applicable_attributes();
847
848     my %seen;
849     my @classes = grep { not $seen{$_->name}++ } map { $_->associated_class } @attrs;
850
851     foreach my $class ( @classes ) { 
852         $class->add_dependent_meta_instance($self);
853     }
854
855     $self->{meta_instance_dependencies} = \@classes;
856 }
857
858 sub remove_meta_instance_dependencies {
859     my $self = shift;
860
861     if ( my $classes = delete $self->{meta_instance_dependencies} ) {
862         foreach my $class ( @$classes ) {
863             $class->remove_dependent_meta_instance($self);
864         }
865
866         return $classes;
867     }
868
869     return;
870
871 }
872
873 sub add_dependent_meta_instance {
874     my ( $self, $metaclass ) = @_;
875     push @{ $self->{dependent_meta_instances} }, $metaclass;
876 }
877
878 sub remove_dependent_meta_instance {
879     my ( $self, $metaclass ) = @_;
880     my $name = $metaclass->name;
881     @$_ = grep { $_->name ne $name } @$_ for $self->{dependent_meta_instances};
882 }
883
884 sub invalidate_meta_instances {
885     my $self = shift;
886     $_->invalidate_meta_instance() for $self, @{ $self->{dependent_meta_instances} };
887 }
888
889 sub invalidate_meta_instance {
890     my $self = shift;
891     undef $self->{_meta_instance};
892 }
893
894 sub has_attribute {
895     my ($self, $attribute_name) = @_;
896     (defined $attribute_name && $attribute_name)
897         || confess "You must define an attribute name";
898     exists $self->get_attribute_map->{$attribute_name};
899 }
900
901 sub get_attribute {
902     my ($self, $attribute_name) = @_;
903     (defined $attribute_name && $attribute_name)
904         || confess "You must define an attribute name";
905     return $self->get_attribute_map->{$attribute_name}
906     # NOTE:
907     # this will return undef anyway, so no need ...
908     #    if $self->has_attribute($attribute_name);
909     #return;
910 }
911
912 sub remove_attribute {
913     my ($self, $attribute_name) = @_;
914     (defined $attribute_name && $attribute_name)
915         || confess "You must define an attribute name";
916     my $removed_attribute = $self->get_attribute_map->{$attribute_name};
917     return unless defined $removed_attribute;
918     delete $self->get_attribute_map->{$attribute_name};
919     $self->invalidate_meta_instances();
920     $removed_attribute->remove_accessors();
921     $removed_attribute->detach_from_class();
922     return $removed_attribute;
923 }
924
925 sub get_attribute_list {
926     my $self = shift;
927     keys %{$self->get_attribute_map};
928 }
929
930 sub get_all_attributes {
931     shift->compute_all_applicable_attributes(@_);
932 }
933
934 sub compute_all_applicable_attributes {
935     my $self = shift;
936     my %attrs = map { %{ $self->initialize($_)->get_attribute_map } } reverse $self->linearized_isa;
937     return values %attrs;
938 }
939
940 sub find_attribute_by_name {
941     my ($self, $attr_name) = @_;
942     foreach my $class ($self->linearized_isa) {
943         # fetch the meta-class ...
944         my $meta = $self->initialize($class);
945         return $meta->get_attribute($attr_name)
946             if $meta->has_attribute($attr_name);
947     }
948     return;
949 }
950
951 # check if we can reinitialize
952 sub is_pristine {
953     my $self = shift;
954
955     # if any local attr is defined
956     return if $self->get_attribute_list;
957
958     # or any non-declared methods
959     if ( my @methods = values %{ $self->get_method_map } ) {
960         my $metaclass = $self->method_metaclass;
961         foreach my $method ( @methods ) {
962             return if $method->isa("Class::MOP::Method::Generated");
963             # FIXME do we need to enforce this too? return unless $method->isa($metaclass);
964         }
965     }
966
967     return 1;
968 }
969
970 ## Class closing
971
972 sub is_mutable   { 1 }
973 sub is_immutable { 0 }
974
975 sub immutable_transformer { $_[0]->{immutable_transformer} }
976 sub _set_immutable_transformer { $_[0]->{immutable_transformer} = $_[1] }
977
978 sub make_immutable {
979     my $self = shift;
980
981     return if $self->is_immutable;
982
983     my $transformer = $self->immutable_transformer
984         || $self->_make_immutable_transformer(@_);
985
986     $self->_set_immutable_transformer($transformer);
987
988     $transformer->make_metaclass_immutable;
989 }
990
991 {
992     my %Default_Immutable_Options = (
993         read_only   => [qw/superclasses/],
994         cannot_call => [
995             qw(
996                 add_method
997                 alias_method
998                 remove_method
999                 add_attribute
1000                 remove_attribute
1001                 remove_package_symbol
1002                 )
1003         ],
1004         memoize => {
1005             class_precedence_list => 'ARRAY',
1006             # FIXME perl 5.10 memoizes this on its own, no need?
1007             linearized_isa                    => 'ARRAY',
1008             get_all_methods                   => 'ARRAY',
1009             get_all_method_names              => 'ARRAY',
1010             compute_all_applicable_attributes => 'ARRAY',
1011             get_meta_instance                 => 'SCALAR',
1012             get_method_map                    => 'SCALAR',
1013         },
1014
1015         # NOTE:
1016         # this is ugly, but so are typeglobs,
1017         # so whattayahgonnadoboutit
1018         # - SL
1019         wrapped => {
1020             add_package_symbol => sub {
1021                 my $original = shift;
1022                 confess "Cannot add package symbols to an immutable metaclass"
1023                     unless ( caller(2) )[3] eq
1024                     'Class::MOP::Package::get_package_symbol';
1025
1026                 # This is a workaround for a bug in 5.8.1 which thinks that
1027                 # goto $original->body
1028                 # is trying to go to a label
1029                 my $body = $original->body;
1030                 goto $body;
1031             },
1032         },
1033     );
1034
1035     sub _default_immutable_transformer_options {
1036         return %Default_Immutable_Options;
1037     }
1038 }
1039
1040 sub _make_immutable_transformer {
1041     my $self = shift;
1042
1043     Class::MOP::Immutable->new(
1044         $self,
1045         $self->_default_immutable_transformer_options,
1046         @_
1047     );
1048 }
1049
1050 sub make_mutable {
1051     my $self = shift;
1052
1053     return if $self->is_mutable;
1054
1055     $self->immutable_transformer->make_metaclass_mutable;
1056 }
1057
1058 1;
1059
1060 __END__
1061
1062 =pod
1063
1064 =head1 NAME
1065
1066 Class::MOP::Class - Class Meta Object
1067
1068 =head1 SYNOPSIS
1069
1070   # assuming that class Foo
1071   # has been defined, you can
1072
1073   # use this for introspection ...
1074
1075   # add a method to Foo ...
1076   Foo->meta->add_method( 'bar' => sub {...} )
1077
1078       # get a list of all the classes searched
1079       # the method dispatcher in the correct order
1080       Foo->meta->class_precedence_list()
1081
1082       # remove a method from Foo
1083       Foo->meta->remove_method('bar');
1084
1085   # or use this to actually create classes ...
1086
1087   Class::MOP::Class->create(
1088       'Bar' => (
1089           version      => '0.01',
1090           superclasses => ['Foo'],
1091           attributes   => [
1092               Class::MOP:: : Attribute->new('$bar'),
1093               Class::MOP:: : Attribute->new('$baz'),
1094           ],
1095           methods => {
1096               calculate_bar => sub {...},
1097               construct_baz => sub {...}
1098           }
1099       )
1100   );
1101
1102 =head1 DESCRIPTION
1103
1104 The Class Protocol is the largest and most complex part of the
1105 Class::MOP meta-object protocol. It controls the introspection and
1106 manipulation of Perl 5 classes, and it can create them as well. The
1107 best way to understand what this module can do, is to read the
1108 documentation for each of its methods.
1109
1110 =head1 INHERITANCE
1111
1112 C<Class::MOP::Class> is a subclass of L<Class::MOP::Module>.
1113
1114 =head1 METHODS
1115
1116 =head2 Class construction
1117
1118 These methods all create new C<Class::MOP::Class> objects. These
1119 objects can represent existing classes, or they can be used to create
1120 new classes from scratch.
1121
1122 The metaclass object for a given class is a singleton. If you attempt
1123 to create a metaclass for the same class twice, you will just get the
1124 existing object.
1125
1126 =over 4
1127
1128 =item B<< Class::MOP::Class->create($package_name, %options) >>
1129
1130 This method creates a new C<Class::MOP::Class> object with the given
1131 package name. It accepts a number of options.
1132
1133 =over 8
1134
1135 =item * version
1136
1137 An optional version number for the newly created package.
1138
1139 =item * authority
1140
1141 An optional authority for the newly created package.
1142
1143 =item * superclasses
1144
1145 An optional array reference of superclass names.
1146
1147 =item * methods
1148
1149 An optional hash reference of methods for the class. The keys of the
1150 hash reference are method names, and values are subroutine references.
1151
1152 =item * attributes
1153
1154 An optional array reference of attributes.
1155
1156 An attribute can be passed as an existing L<Class::MOP::Attribute>
1157 object, I<or> or as a hash reference of options which will be passed
1158 to the attribute metaclass's constructor.
1159
1160 =back
1161
1162 =item B<< Class::MOP::Class->create_anon_class(%options) >>
1163
1164 This method works just like C<< Class::MOP::Class->create >> but it
1165 creates an "anonymous" class. In fact, the class does have a name, but
1166 that name is a unique name generated internally by this module.
1167
1168 It accepts the same C<superclasses>, C<methods>, and C<attributes>
1169 parameters that C<create> accepts.
1170
1171 Anonymous classes are destroyed once the metaclass they are attached
1172 to goes out of scope, and will be removed from Perl's internal symbol
1173 table.
1174
1175 All instances of an anonymous class keep a special reference to the
1176 metaclass object, which prevents the metaclass from going out of scope
1177 while any instances exist.
1178
1179 This only works if the instance if based on a hash reference, however.
1180
1181 =item B<< Class::MOP::Class->initialize($package_name, %options) >>
1182
1183 This method will initialize a C<Class::MOP::Class> object for the
1184 named package. Unlike C<create>, this method I<will not> create a new
1185 class.
1186
1187 The purpose of this method is to retrieve a C<Class::MOP::Class>
1188 object for introspecting an existing class.
1189
1190 If an existing C<Class::MOP::Class> object exists for the named
1191 package, it will be returned, and any options provided will be
1192 ignored!
1193
1194 If the object does not yet exist, it will be created.
1195
1196 The valid options that can be passed to this method are
1197 C<attribute_metaclass>, C<method_metaclass>,
1198 C<wrapped_method_metaclass>, and C<instance_metaclass>. These are all
1199 optional, and default to the appropriate class in the C<Class::MOP>
1200 distribution.
1201
1202 =back
1203
1204 =head2 Object instance construction and cloning
1205
1206 These methods are all related to creating and/or cloning object
1207 instances.
1208
1209 =over 4
1210
1211 =item B<< $metaclass->clone_object($instance, %params) >>
1212
1213 This method clones an existing object instance. Any parameters you
1214 provide are will override existing attribute values in the object.
1215
1216 This is a convenience method for cloning an object instance, then
1217 blessing it into the appropriate package.
1218
1219 You could implement a clone method in your class, using this method:
1220
1221   sub clone {
1222       my ($self, %params) = @_;
1223       $self->meta->clone_object($self, %params);
1224   }
1225
1226 =item B<< $metaclass->rebless_instance($instance, %params) >>
1227
1228 This method changes the class of C<$instance> to the metaclass's class.
1229
1230 You can only rebless an instance into a subclass of its current
1231 class. If you pass any additional parameters, these will be treated
1232 like constructor parameters and used to initialize the object's
1233 attributes. Any existing attributes that are already set will be
1234 overwritten.
1235
1236 =item B<< $metaclass->new_object(%params) >>
1237
1238 This method is used to create a new object of the metaclass's
1239 class. Any parameters you provide are used to initialize the
1240 instance's attributes.
1241
1242 =item B<< $metaclass->instance_metaclass >>
1243
1244 Returns the class name of the instance metaclass, see
1245 L<Class::MOP::Instance> for more information on the instance
1246 metaclass.
1247
1248 =item B<< $metaclass->get_meta_instance >>
1249
1250 Returns an instance of the C<instance_metaclass> to be used in the
1251 construction of a new instance of the class.
1252
1253 =back
1254
1255 =head2 Informational predicates
1256
1257 These are a few predicate methods for asking information about the
1258 class itself.
1259
1260 =over 4
1261
1262 =item B<< $metaclass->is_anon_class >>
1263
1264 This returns true if the class was created by calling C<<
1265 Class::MOP::Class->create_anon_class >>.
1266
1267 =item B<< $metaclass->is_mutable >>
1268
1269 This returns true if the class is still mutable.
1270
1271 =item B<< $metaclass->is_immutable >>
1272
1273 This returns true if the class has been made immutable.
1274
1275 =item B<< $metaclass->is_pristine >>
1276
1277 A class is I<not> pristine if it has non-inherited attributes or if it
1278 has any generated methods.
1279
1280 =back
1281
1282 =head2 Inheritance Relationships
1283
1284 =over 4
1285
1286 =item B<< $metaclass->superclasses(@superclasses) >>
1287
1288 This is a read-write accessor which represents the superclass
1289 relationships of the metaclass's class.
1290
1291 This is basically sugar around getting and setting C<@ISA>.
1292
1293 =item B<< $metaclass->class_precedence_list >>
1294
1295 This returns a list of all of the class's ancestor classes. The
1296 classes are returned in method dispatch order.
1297
1298 =item B<< $metaclass->linearized_isa >>
1299
1300 This returns a list based on C<class_precedence_list> but with all
1301 duplicates removed.
1302
1303 =item B<< $metaclass->subclasses >>
1304
1305 This returns a list of subclasses for this class.
1306
1307 =back
1308
1309 =head2 Method introspection and creation
1310
1311 These methods allow you to introspect a class's methods, as well as
1312 add, remove, or change methods.
1313
1314 Determining what is truly a method in a Perl 5 class requires some
1315 heuristics (aka guessing).
1316
1317 Methods defined outside the package with a fully qualified name (C<sub
1318 Package::name { ... }>) will be included. Similarly, methods named
1319 with a fully qualified name using L<Sub::Name> are also included.
1320
1321 However, we attempt to ignore imported functions.
1322
1323 Ultimately, we are using heuristics to determine what truly is a
1324 method in a class, and these heuristics may get the wrong answer in
1325 some edge cases. However, for most "normal" cases the heuristics work
1326 correctly.
1327
1328 =over 4
1329
1330 =item B<< $metaclass->get_method($method_name) >>
1331
1332 This will return a L<Class::MOP::Method> for the specified
1333 C<$method_name>. If the class does not have the specified method, it
1334 returns C<undef>
1335
1336 =item B<< $metaclass->has_method($method_name) >>
1337
1338 Returns a boolean indicating whether or not the class defines the
1339 named method. It does not include methods inherited from parent
1340 classes.
1341
1342 =item B<< $metaclass->get_method_map >>
1343
1344 Returns a hash reference representing the methods defined in this
1345 class. The keys are method names and the values are
1346 L<Class::MOP::Method> objects.
1347
1348 =item B<< $metaclass->get_method_list >>
1349
1350 This will return a list of method I<names> for all methods defined in
1351 this class.
1352
1353 =item B<< $metaclass->get_all_methods >>
1354
1355 This will traverse the inheritance hierarchy and return a list of all
1356 the L<Class::MOP::Method> objects for this class and its parents.
1357
1358 =item B<< $metaclass->find_method_by_name($method_name) >>
1359
1360 This will return a L<Class::MOP::Method> for the specified
1361 C<$method_name>. If the class does not have the specified method, it
1362 returns C<undef>
1363
1364 Unlike C<get_method>, this method I<will> look for the named method in
1365 superclasses.
1366
1367 =item B<< $metaclass->get_all_method_names >>
1368
1369 This will return a list of method I<names> for all of this class's
1370 methods, including inherited methods.
1371
1372 =item B<< $metaclass->find_all_methods_by_name($method_name) >>
1373
1374 This method looks for the named method in the class and all of its
1375 parents. It returns every matching method it finds in the inheritance
1376 tree, so it returns a list of methods.
1377
1378 Each method is returned as a hash reference with three keys. The keys
1379 are C<name>, C<class>, and C<code>. The C<code> key has a
1380 L<Class::MOP::Method> object as its value.
1381
1382 The list of methods is distinct.
1383
1384 =item B<< $metaclass->find_next_method_by_name($method_name) >>
1385
1386 This method returns the first method in any superclass matching the
1387 given name. It is effectively the method that C<SUPER::$method_name>
1388 would dispatch to.
1389
1390 =item B<< $metaclass->add_method($method_name, $method) >>
1391
1392 This method takes a method name and a subroutine reference, and adds
1393 the method to the class.
1394
1395 The subroutine reference can be a L<Class::MOP::Method>, and you are
1396 strongly encouraged to pass a meta method object instead of a code
1397 reference. If you do so, that object gets stored as part of the
1398 class's method map directly. If not, the meta information will have to
1399 be recreated later, and may be incorrect.
1400
1401 If you provide a method object, this method will clone that object if
1402 the object's package name does not match the class name. This lets us
1403 track the original source of any methods added from other classes
1404 (notably Moose roles).
1405
1406 =item B<< $metaclass->remove_method($method_name) >>
1407
1408 Remove the named method from the class. This method returns the
1409 L<Class::MOP::Method> object for the method.
1410
1411 =item B<< $metaclass->method_metaclass >>
1412
1413 Returns the class name of the method metaclass, see
1414 L<Class::MOP::Method> for more information on the method metaclass.
1415
1416 =item B<< $metaclass->wrapped_method_metaclass >>
1417
1418 Returns the class name of the wrapped method metaclass, see
1419 L<Class::MOP::Method::Wrapped> for more information on the wrapped
1420 method metaclass.
1421
1422 =back
1423
1424 =head2 Attribute introspection and creation
1425
1426 Because Perl 5 does not have a core concept of attributes in classes,
1427 we can only return information about attributes which have been added
1428 via this class's methods. We cannot discover information about
1429 attributes which are defined in terms of "regular" Perl 5 methods.
1430
1431 =over 4
1432
1433 =item B<< $metaclass->get_attribute($attribute_name) >>
1434
1435 This will return a L<Class::MOP::Attribute> for the specified
1436 C<$attribute_name>. If the class does not have the specified
1437 attribute, it returns C<undef>
1438
1439 =item B<< $metaclass->has_attribute($attribute_name) >>
1440
1441 Returns a boolean indicating whether or not the class defines the
1442 named attribute. It does not include attributes inherited from parent
1443 classes.
1444
1445 =item B<< $metaclass->get_attribute_map >>
1446
1447 Returns a hash reference representing the attributes defined in this
1448 class. The keys are attribute names and the values are
1449 L<Class::MOP::Attribute> objects.
1450
1451 =item B<< $metaclass->get_attribute_list >>
1452
1453 This will return a list of attributes I<names> for all attributes
1454 defined in this class.
1455
1456 =item B<< $metaclass->get_all_attributes >>
1457
1458 This will traverse the inheritance hierarchy and return a list of all
1459 the L<Class::MOP::Attribute> objects for this class and its parents.
1460
1461 This method can also be called as C<compute_all_applicable_attributes>.
1462
1463 =item B<< $metaclass->find_attribute_by_name($attribute_name) >>
1464
1465 This will return a L<Class::MOP::Attribute> for the specified
1466 C<$attribute_name>. If the class does not have the specified
1467 attribute, it returns C<undef>
1468
1469 Unlike C<get_attribute>, this attribute I<will> look for the named
1470 attribute in superclasses.
1471
1472 =item B<< $metaclass->add_attribute(...) >>
1473
1474 This method accepts either an existing L<Class::MOP::Attribute>
1475 object, or parameters suitable for passing to that class's C<new>
1476 method.
1477
1478 The attribute provided will be added to the class.
1479
1480 Any accessor methods defined by the attribute will be added to the
1481 class when the attribute is added.
1482
1483 If an attribute of the same name already exists, the old attribute
1484 will be removed first.
1485
1486 =item B<< $metaclass->remove_attribute($attribute_name) >>
1487
1488 This will remove the named attribute from the class, and
1489 L<Class::MOP::Attribute> object.
1490
1491 Removing an attribute also removes any accessor methods defined by the
1492 attribute.
1493
1494 However, note that removing an attribute will only affect I<future>
1495 object instances created for this class, not existing instances.
1496
1497 =item B<< $metaclass->attribute_metaclass >>
1498
1499 Returns the class name of the attribute metaclass for this class. By
1500 default, this is L<Class::MOP::Attribute>.  for more information on
1501
1502 =back
1503
1504 =head2 Class Immutability
1505
1506 Making a class immutable "freezes" the class definition. You can no
1507 longer call methods which alter the class, such as adding or removing
1508 methods or attributes.
1509
1510 Making a class immutable lets us optimize the class by inlining some
1511 methods, and also allows us to optimize some methods on the metaclass
1512 object itself.
1513
1514 The immutabilization system in L<Moose> takes much greater advantage
1515 of the inlining features than Class::MOP itself does.
1516
1517 =over 4
1518
1519 =item B<< $metaclass->make_immutable(%options) >>
1520
1521 This method will create an immutable transformer and uses it to make
1522 the class and its metaclass object immutable.
1523
1524 Details of how immutabilization works are in L<Class::MOP::Immutable>
1525 documentation.
1526
1527 =item B<< $metaclass->make_mutable >>
1528
1529 Calling this method reverse the immutabilization transformation.
1530
1531 =item B<< $metaclass->immutable_transformer >>
1532
1533 If the class has been made immutable previously, this returns the
1534 L<Class::MOP::Immutable> object that was created to do the
1535 transformation.
1536
1537 If the class was never made immutable, this method will die.
1538
1539 =back
1540
1541 =head2 Method Modifiers
1542
1543 Method modifiers are hooks which allow a method to be wrapped with
1544 I<before>, I<after> and I<around> method modifiers. Every time a
1545 method is called, it's modifiers are also called.
1546
1547 A class can modify its own methods, as well as methods defined in
1548 parent classes.
1549
1550 =head3 How method modifiers work?
1551
1552 Method modifiers work by wrapping the original method and then
1553 replacing it in the class's symbol table. The wrappers will handle
1554 calling all the modifiers in the appropriate order and preserving the
1555 calling context for the original method.
1556
1557 The return values of C<before> and C<after> modifiers are
1558 ignored. This is because their purpose is B<not> to filter the input
1559 and output of the primary method (this is done with an I<around>
1560 modifier).
1561
1562 This may seem like an odd restriction to some, but doing this allows
1563 for simple code to be added at the beginning or end of a method call
1564 without altering the function of the wrapped method or placing any
1565 extra responsibility on the code of the modifier.
1566
1567 Of course if you have more complex needs, you can use the C<around>
1568 modifier which allows you to change both the parameters passed to the
1569 wrapped method, as well as its return value.
1570
1571 Before and around modifiers are called in last-defined-first-called
1572 order, while after modifiers are called in first-defined-first-called
1573 order. So the call tree might looks something like this:
1574
1575   before 2
1576    before 1
1577     around 2
1578      around 1
1579       primary
1580      around 1
1581     around 2
1582    after 1
1583   after 2
1584
1585 =head3 What is the performance impact?
1586
1587 Of course there is a performance cost associated with method
1588 modifiers, but we have made every effort to make that cost directly
1589 proportional to the number of modifier features you utilize.
1590
1591 The wrapping method does it's best to B<only> do as much work as it
1592 absolutely needs to. In order to do this we have moved some of the
1593 performance costs to set-up time, where they are easier to amortize.
1594
1595 All this said, our benchmarks have indicated the following:
1596
1597   simple wrapper with no modifiers             100% slower
1598   simple wrapper with simple before modifier   400% slower
1599   simple wrapper with simple after modifier    450% slower
1600   simple wrapper with simple around modifier   500-550% slower
1601   simple wrapper with all 3 modifiers          1100% slower
1602
1603 These numbers may seem daunting, but you must remember, every feature
1604 comes with some cost. To put things in perspective, just doing a
1605 simple C<AUTOLOAD> which does nothing but extract the name of the
1606 method called and return it costs about 400% over a normal method
1607 call.
1608
1609 =over 4
1610
1611 =item B<< $metaclass->add_before_method_modifier($method_name, $code) >>
1612
1613 This wraps the specified method with the supplied subroutine
1614 reference. The modifier will be called as a method itself, and will
1615 receive the same arguments as are passed to the method.
1616
1617 When the modifier exits, the wrapped method will be called.
1618
1619 The return value of the modifier will be ignored.
1620
1621 =item B<< $metaclass->add_after_method_modifier($method_name, $code) >>
1622
1623 This wraps the specified method with the supplied subroutine
1624 reference. The modifier will be called as a method itself, and will
1625 receive the same arguments as are passed to the method.
1626
1627 When the wrapped methods exits, the modifier will be called.
1628
1629 The return value of the modifier will be ignored.
1630
1631 =item B<< $metaclass->add_around_method_modifier($method_name, $code) >>
1632
1633 This wraps the specified method with the supplied subroutine
1634 reference.
1635
1636 The first argument passed to the modifier will be a subroutine
1637 reference to the wrapped method. The second argument is the object,
1638 and after that come any arguments passed when the method is called.
1639
1640 The around modifier can choose to call the original method, as well as
1641 what arguments to pass if it does so.
1642
1643 The return value of the modifier is what will be seen by the caller.
1644
1645 =back
1646
1647 =head2 Introspection
1648
1649 =over 4
1650
1651 =item B<< Class::MOP::Class->meta >>
1652
1653 This will return a L<Class::MOP::Class> instance for this class.
1654
1655 It should also be noted that L<Class::MOP> will actually bootstrap
1656 this module by installing a number of attribute meta-objects into its
1657 metaclass.
1658
1659 =back
1660
1661 =head1 AUTHORS
1662
1663 Stevan Little E<lt>stevan@iinteractive.comE<gt>
1664
1665 =head1 COPYRIGHT AND LICENSE
1666
1667 Copyright 2006-2009 by Infinity Interactive, Inc.
1668
1669 L<http://www.iinteractive.com>
1670
1671 This library is free software; you can redistribute it and/or modify
1672 it under the same terms as Perl itself.
1673
1674 =cut