X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=examples%2FC3MethodDispatchOrder.pod;h=b635f5683f6843553490825c3d513010cc6d7476;hb=33ecbaa40bbcda7518cb3e5477d357e6b3d95ff6;hp=a04e63c4961ef8d6c6eef242fdd152eade2fc82f;hpb=f3f5bd3405b08b20ab8719ab7670277dd732c492;p=gitmo%2FClass-MOP.git diff --git a/examples/C3MethodDispatchOrder.pod b/examples/C3MethodDispatchOrder.pod index a04e63c..b635f56 100644 --- a/examples/C3MethodDispatchOrder.pod +++ b/examples/C3MethodDispatchOrder.pod @@ -8,11 +8,11 @@ use warnings; use Carp 'confess'; use Algorithm::C3; -our $VERSION = '0.01'; +our $VERSION = '0.03'; use base 'Class::MOP::Class'; -my $_find_method_in_superclass = sub { +my $_find_method = sub { my ($class, $method) = @_; foreach my $super ($class->class_precedence_list) { return $super->meta->get_method($method) @@ -20,35 +20,45 @@ my $_find_method_in_superclass = sub { } }; -sub initialize { - my $class = shift; - my $meta = $class->SUPER::initialize(@_); - $meta->add_method('AUTOLOAD' => sub { - my $meta = $_[0]->meta; - my $method_name; - { - no strict 'refs'; - my $label = ${$meta->name . '::AUTOLOAD'}; - $method_name = (split /\:\:/ => $label)[-1]; - } - my $method = $_find_method_in_superclass->($meta, $method_name); +C3MethodDispatchOrder->meta->add_around_method_modifier('initialize' => sub { + my $cont = shift; + my $meta = $cont->(@_); + + # we need to look at $AUTOLOAD in the package where the coderef belongs + # if subname works, then it'll be where this AUTOLOAD method was installed + # otherwise, it'll be $C3MethodDispatchOrder::AUTOLOAD. get_code_info + # tells us where AUTOLOAD will look + my $autoload; + $autoload = sub { + my ($package) = Class::MOP::get_code_info($autoload); + my $label = ${ $package->meta->get_package_symbol('$AUTOLOAD') }; + my $method_name = (split /\:\:/ => $label)[-1]; + my $method = $_find_method->($_[0]->meta, $method_name); (defined $method) || confess "Method ($method_name) not found"; goto &$method; - }); + }; + + $meta->add_method('AUTOLOAD' => $autoload) + unless $meta->has_method('AUTOLOAD'); + $meta->add_method('can' => sub { - $_find_method_in_superclass->($_[0]->meta, $_[1]); - }); - return $meta; -} + $_find_method->($_[0]->meta, $_[1]); + }) unless $meta->has_method('can'); + + return $meta; +}); sub superclasses { my $self = shift; - no strict 'refs'; + + $self->add_package_symbol('@SUPERS' => []) + unless $self->has_package_symbol('@SUPERS'); + if (@_) { my @supers = @_; - @{$self->name . '::SUPERS'} = @supers; + @{$self->get_package_symbol('@SUPERS')} = @supers; } - @{$self->name . '::SUPERS'}; + @{$self->get_package_symbol('@SUPERS')}; } sub class_precedence_list { @@ -108,13 +118,25 @@ C3MethodDispatchOrder - An example attribute metaclass for changing to C3 method =head1 DESCRIPTION -=head1 AUTHOR +This is an example of how you could change the method dispatch order of a +class using L. Using the L module, this repleces +the normal depth-first left-to-right perl dispatch order with the C3 method +dispatch order (see the L or L docs for more +information about this). + +This example could be used as a template for other method dispatch orders +as well, all that is required is to write a the C method +which will return a linearized list of classes to dispatch along. + +=head1 AUTHORS Stevan Little Estevan@iinteractive.comE +Yuval Kogman Enothingmuch@woobling.comE + =head1 COPYRIGHT AND LICENSE -Copyright 2006 by Infinity Interactive, Inc. +Copyright 2006-2008 by Infinity Interactive, Inc. L