The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

NEXT.pm - Provide a pseudo-class NEXT that allows method redispatch

SYNOPSIS

        use NEXT;

        package A;
        sub A::method   { print "$_[0]: A method\n";   $_[0]->NEXT::method() }
        sub A::DESTROY  { print "$_[0]: A dtor\n";     $_[0]->NEXT::DESTROY() }

        package B;
        use base qw( A );
        sub B::AUTOLOAD { print "$_[0]: B AUTOLOAD\n"; $_[0]->NEXT::AUTOLOAD() }
        sub B::DESTROY  { print "$_[0]: B dtor\n";     $_[0]->NEXT::DESTROY() }

        package C;
        sub C::method   { print "$_[0]: C method\n";   $_[0]->NEXT::method() }
        sub C::AUTOLOAD { print "$_[0]: C AUTOLOAD\n"; $_[0]->NEXT::AUTOLOAD() }
        sub C::DESTROY  { print "$_[0]: C dtor\n";     $_[0]->NEXT::DESTROY() }

        package D;
        use base qw( B C );
        sub D::method   { print "$_[0]: D method\n";   $_[0]->NEXT::method() }
        sub D::AUTOLOAD { print "$_[0]: D AUTOLOAD\n"; $_[0]->NEXT::AUTOLOAD() }
        sub D::DESTROY  { print "$_[0]: D dtor\n";     $_[0]->NEXT::DESTROY() }

        package main;

        my $obj = bless {}, "D";

        $obj->method();         # Calls D::method, A::method, C::method
        $obj->missing_method(); # Calls D::AUTOLOAD, B::AUTOLOAD, C::AUTOLOAD

        # Clean-up calls D::DESTROY, B::DESTROY, A::DESTROY, C::DESTROY

DESCRIPTION

NEXT.pm adds a pseudoclass named NEXT to any program that uses it. If a method m calls $self-NEXT::m()>, the call to m is redispatched as if the calling method had not originally been found.

In other words, a call to $self-NEXT::m()> resumes the depth-first, left-to-right search of parent classes that resulted in the original call to m.

A typical use would be in the destructors of a class hierarchy, as illustrated in the synopsis above. Each class in the hierarchy has a DESTROY method that performs some class-specific action and then redispatches the call up the hierarchy. As a result, when an object of class D is destroyed, the destructors of all its parent classes are called (in depth-first, left-to-right order).

Another typical use of redispatch would be in AUTOLOAD'ed methods. If such a method determined that it was not able to handle a particular call, it might choose to redispatch that call, in the hope that some other AUTOLOAD (above it, or to its left) might do better.

Note that it is a fatal error for any method (including AUTOLOAD) to attempt to redispatch any method except itself. For example:

        sub D::oops { print "oops!\n"; $_[0]->NEXT::other_method() }

AUTHOR

Damian Conway (damian@conway.org)

BUGS AND IRRITATIONS

Because it's a module, not an integral part of the interpreter, NEXT.pm has to guess where the surrounding call was found in the method look-up sequence. In the presence of diamond inheritance patterns it occasionally guesses wrong.

It's also too slow (despite caching).

Comment, suggestions, and patches welcome.

COPYRIGHT

 Copyright (c) 2000, Damian Conway. All Rights Reserved.
 This module is free software. It may be used, redistributed
and/or modified under the terms of the Perl Artistic License
     (see http://www.perl.com/perl/misc/Artistic.html)