1*0Sstevel@tonic-gatepackage NEXT; 2*0Sstevel@tonic-gate$VERSION = '0.60'; 3*0Sstevel@tonic-gateuse Carp; 4*0Sstevel@tonic-gateuse strict; 5*0Sstevel@tonic-gate 6*0Sstevel@tonic-gatesub NEXT::ELSEWHERE::ancestors 7*0Sstevel@tonic-gate{ 8*0Sstevel@tonic-gate my @inlist = shift; 9*0Sstevel@tonic-gate my @outlist = (); 10*0Sstevel@tonic-gate while (my $next = shift @inlist) { 11*0Sstevel@tonic-gate push @outlist, $next; 12*0Sstevel@tonic-gate no strict 'refs'; 13*0Sstevel@tonic-gate unshift @inlist, @{"$outlist[-1]::ISA"}; 14*0Sstevel@tonic-gate } 15*0Sstevel@tonic-gate return @outlist; 16*0Sstevel@tonic-gate} 17*0Sstevel@tonic-gate 18*0Sstevel@tonic-gatesub NEXT::ELSEWHERE::ordered_ancestors 19*0Sstevel@tonic-gate{ 20*0Sstevel@tonic-gate my @inlist = shift; 21*0Sstevel@tonic-gate my @outlist = (); 22*0Sstevel@tonic-gate while (my $next = shift @inlist) { 23*0Sstevel@tonic-gate push @outlist, $next; 24*0Sstevel@tonic-gate no strict 'refs'; 25*0Sstevel@tonic-gate push @inlist, @{"$outlist[-1]::ISA"}; 26*0Sstevel@tonic-gate } 27*0Sstevel@tonic-gate return sort { $a->isa($b) ? -1 28*0Sstevel@tonic-gate : $b->isa($a) ? +1 29*0Sstevel@tonic-gate : 0 } @outlist; 30*0Sstevel@tonic-gate} 31*0Sstevel@tonic-gate 32*0Sstevel@tonic-gatesub AUTOLOAD 33*0Sstevel@tonic-gate{ 34*0Sstevel@tonic-gate my ($self) = @_; 35*0Sstevel@tonic-gate my $caller = (caller(1))[3]; 36*0Sstevel@tonic-gate my $wanted = $NEXT::AUTOLOAD || 'NEXT::AUTOLOAD'; 37*0Sstevel@tonic-gate undef $NEXT::AUTOLOAD; 38*0Sstevel@tonic-gate my ($caller_class, $caller_method) = $caller =~ m{(.*)::(.*)}g; 39*0Sstevel@tonic-gate my ($wanted_class, $wanted_method) = $wanted =~ m{(.*)::(.*)}g; 40*0Sstevel@tonic-gate croak "Can't call $wanted from $caller" 41*0Sstevel@tonic-gate unless $caller_method eq $wanted_method; 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate local ($NEXT::NEXT{$self,$wanted_method}, $NEXT::SEEN) = 44*0Sstevel@tonic-gate ($NEXT::NEXT{$self,$wanted_method}, $NEXT::SEEN); 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate unless ($NEXT::NEXT{$self,$wanted_method}) { 48*0Sstevel@tonic-gate my @forebears = 49*0Sstevel@tonic-gate NEXT::ELSEWHERE::ancestors ref $self || $self, 50*0Sstevel@tonic-gate $wanted_class; 51*0Sstevel@tonic-gate while (@forebears) { 52*0Sstevel@tonic-gate last if shift @forebears eq $caller_class 53*0Sstevel@tonic-gate } 54*0Sstevel@tonic-gate no strict 'refs'; 55*0Sstevel@tonic-gate @{$NEXT::NEXT{$self,$wanted_method}} = 56*0Sstevel@tonic-gate map { *{"${_}::$caller_method"}{CODE}||() } @forebears 57*0Sstevel@tonic-gate unless $wanted_method eq 'AUTOLOAD'; 58*0Sstevel@tonic-gate @{$NEXT::NEXT{$self,$wanted_method}} = 59*0Sstevel@tonic-gate map { (*{"${_}::AUTOLOAD"}{CODE}) ? "${_}::AUTOLOAD" : ()} @forebears 60*0Sstevel@tonic-gate unless @{$NEXT::NEXT{$self,$wanted_method}||[]}; 61*0Sstevel@tonic-gate $NEXT::SEEN->{$self,*{$caller}{CODE}}++; 62*0Sstevel@tonic-gate } 63*0Sstevel@tonic-gate my $call_method = shift @{$NEXT::NEXT{$self,$wanted_method}}; 64*0Sstevel@tonic-gate while ($wanted_class =~ /^NEXT\b.*\b(UNSEEN|DISTINCT)\b/ 65*0Sstevel@tonic-gate && defined $call_method 66*0Sstevel@tonic-gate && $NEXT::SEEN->{$self,$call_method}++) { 67*0Sstevel@tonic-gate $call_method = shift @{$NEXT::NEXT{$self,$wanted_method}}; 68*0Sstevel@tonic-gate } 69*0Sstevel@tonic-gate unless (defined $call_method) { 70*0Sstevel@tonic-gate return unless $wanted_class =~ /^NEXT:.*:ACTUAL/; 71*0Sstevel@tonic-gate (local $Carp::CarpLevel)++; 72*0Sstevel@tonic-gate croak qq(Can't locate object method "$wanted_method" ), 73*0Sstevel@tonic-gate qq(via package "$caller_class"); 74*0Sstevel@tonic-gate }; 75*0Sstevel@tonic-gate return $self->$call_method(@_[1..$#_]) if ref $call_method eq 'CODE'; 76*0Sstevel@tonic-gate no strict 'refs'; 77*0Sstevel@tonic-gate ($wanted_method=${$caller_class."::AUTOLOAD"}) =~ s/.*::// 78*0Sstevel@tonic-gate if $wanted_method eq 'AUTOLOAD'; 79*0Sstevel@tonic-gate $$call_method = $caller_class."::NEXT::".$wanted_method; 80*0Sstevel@tonic-gate return $call_method->(@_); 81*0Sstevel@tonic-gate} 82*0Sstevel@tonic-gate 83*0Sstevel@tonic-gateno strict 'vars'; 84*0Sstevel@tonic-gatepackage NEXT::UNSEEN; @ISA = 'NEXT'; 85*0Sstevel@tonic-gatepackage NEXT::DISTINCT; @ISA = 'NEXT'; 86*0Sstevel@tonic-gatepackage NEXT::ACTUAL; @ISA = 'NEXT'; 87*0Sstevel@tonic-gatepackage NEXT::ACTUAL::UNSEEN; @ISA = 'NEXT'; 88*0Sstevel@tonic-gatepackage NEXT::ACTUAL::DISTINCT; @ISA = 'NEXT'; 89*0Sstevel@tonic-gatepackage NEXT::UNSEEN::ACTUAL; @ISA = 'NEXT'; 90*0Sstevel@tonic-gatepackage NEXT::DISTINCT::ACTUAL; @ISA = 'NEXT'; 91*0Sstevel@tonic-gate 92*0Sstevel@tonic-gatepackage EVERY::LAST; @ISA = 'EVERY'; 93*0Sstevel@tonic-gatepackage EVERY; @ISA = 'NEXT'; 94*0Sstevel@tonic-gatesub AUTOLOAD 95*0Sstevel@tonic-gate{ 96*0Sstevel@tonic-gate my ($self) = @_; 97*0Sstevel@tonic-gate my $caller = (caller(1))[3]; 98*0Sstevel@tonic-gate my $wanted = $EVERY::AUTOLOAD || 'EVERY::AUTOLOAD'; 99*0Sstevel@tonic-gate undef $EVERY::AUTOLOAD; 100*0Sstevel@tonic-gate my ($wanted_class, $wanted_method) = $wanted =~ m{(.*)::(.*)}g; 101*0Sstevel@tonic-gate 102*0Sstevel@tonic-gate local $NEXT::ALREADY_IN_EVERY{$self,$wanted_method} = 103*0Sstevel@tonic-gate $NEXT::ALREADY_IN_EVERY{$self,$wanted_method}; 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate return if $NEXT::ALREADY_IN_EVERY{$self,$wanted_method}++; 106*0Sstevel@tonic-gate 107*0Sstevel@tonic-gate my @forebears = NEXT::ELSEWHERE::ordered_ancestors ref $self || $self, 108*0Sstevel@tonic-gate $wanted_class; 109*0Sstevel@tonic-gate @forebears = reverse @forebears if $wanted_class =~ /\bLAST\b/; 110*0Sstevel@tonic-gate no strict 'refs'; 111*0Sstevel@tonic-gate my %seen; 112*0Sstevel@tonic-gate my @every = map { my $sub = "${_}::$wanted_method"; 113*0Sstevel@tonic-gate !*{$sub}{CODE} || $seen{$sub}++ ? () : $sub 114*0Sstevel@tonic-gate } @forebears 115*0Sstevel@tonic-gate unless $wanted_method eq 'AUTOLOAD'; 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gate my $want = wantarray; 118*0Sstevel@tonic-gate if (@every) { 119*0Sstevel@tonic-gate if ($want) { 120*0Sstevel@tonic-gate return map {($_, [$self->$_(@_[1..$#_])])} @every; 121*0Sstevel@tonic-gate } 122*0Sstevel@tonic-gate elsif (defined $want) { 123*0Sstevel@tonic-gate return { map {($_, scalar($self->$_(@_[1..$#_])))} 124*0Sstevel@tonic-gate @every 125*0Sstevel@tonic-gate }; 126*0Sstevel@tonic-gate } 127*0Sstevel@tonic-gate else { 128*0Sstevel@tonic-gate $self->$_(@_[1..$#_]) for @every; 129*0Sstevel@tonic-gate return; 130*0Sstevel@tonic-gate } 131*0Sstevel@tonic-gate } 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate @every = map { my $sub = "${_}::AUTOLOAD"; 134*0Sstevel@tonic-gate !*{$sub}{CODE} || $seen{$sub}++ ? () : "${_}::AUTOLOAD" 135*0Sstevel@tonic-gate } @forebears; 136*0Sstevel@tonic-gate if ($want) { 137*0Sstevel@tonic-gate return map { $$_ = ref($self)."::EVERY::".$wanted_method; 138*0Sstevel@tonic-gate ($_, [$self->$_(@_[1..$#_])]); 139*0Sstevel@tonic-gate } @every; 140*0Sstevel@tonic-gate } 141*0Sstevel@tonic-gate elsif (defined $want) { 142*0Sstevel@tonic-gate return { map { $$_ = ref($self)."::EVERY::".$wanted_method; 143*0Sstevel@tonic-gate ($_, scalar($self->$_(@_[1..$#_]))) 144*0Sstevel@tonic-gate } @every 145*0Sstevel@tonic-gate }; 146*0Sstevel@tonic-gate } 147*0Sstevel@tonic-gate else { 148*0Sstevel@tonic-gate for (@every) { 149*0Sstevel@tonic-gate $$_ = ref($self)."::EVERY::".$wanted_method; 150*0Sstevel@tonic-gate $self->$_(@_[1..$#_]); 151*0Sstevel@tonic-gate } 152*0Sstevel@tonic-gate return; 153*0Sstevel@tonic-gate } 154*0Sstevel@tonic-gate} 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate 157*0Sstevel@tonic-gate1; 158*0Sstevel@tonic-gate 159*0Sstevel@tonic-gate__END__ 160*0Sstevel@tonic-gate 161*0Sstevel@tonic-gate=head1 NAME 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gateNEXT.pm - Provide a pseudo-class NEXT (et al) that allows method redispatch 164*0Sstevel@tonic-gate 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate=head1 SYNOPSIS 167*0Sstevel@tonic-gate 168*0Sstevel@tonic-gate use NEXT; 169*0Sstevel@tonic-gate 170*0Sstevel@tonic-gate package A; 171*0Sstevel@tonic-gate sub A::method { print "$_[0]: A method\n"; $_[0]->NEXT::method() } 172*0Sstevel@tonic-gate sub A::DESTROY { print "$_[0]: A dtor\n"; $_[0]->NEXT::DESTROY() } 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate package B; 175*0Sstevel@tonic-gate use base qw( A ); 176*0Sstevel@tonic-gate sub B::AUTOLOAD { print "$_[0]: B AUTOLOAD\n"; $_[0]->NEXT::AUTOLOAD() } 177*0Sstevel@tonic-gate sub B::DESTROY { print "$_[0]: B dtor\n"; $_[0]->NEXT::DESTROY() } 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate package C; 180*0Sstevel@tonic-gate sub C::method { print "$_[0]: C method\n"; $_[0]->NEXT::method() } 181*0Sstevel@tonic-gate sub C::AUTOLOAD { print "$_[0]: C AUTOLOAD\n"; $_[0]->NEXT::AUTOLOAD() } 182*0Sstevel@tonic-gate sub C::DESTROY { print "$_[0]: C dtor\n"; $_[0]->NEXT::DESTROY() } 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate package D; 185*0Sstevel@tonic-gate use base qw( B C ); 186*0Sstevel@tonic-gate sub D::method { print "$_[0]: D method\n"; $_[0]->NEXT::method() } 187*0Sstevel@tonic-gate sub D::AUTOLOAD { print "$_[0]: D AUTOLOAD\n"; $_[0]->NEXT::AUTOLOAD() } 188*0Sstevel@tonic-gate sub D::DESTROY { print "$_[0]: D dtor\n"; $_[0]->NEXT::DESTROY() } 189*0Sstevel@tonic-gate 190*0Sstevel@tonic-gate package main; 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate my $obj = bless {}, "D"; 193*0Sstevel@tonic-gate 194*0Sstevel@tonic-gate $obj->method(); # Calls D::method, A::method, C::method 195*0Sstevel@tonic-gate $obj->missing_method(); # Calls D::AUTOLOAD, B::AUTOLOAD, C::AUTOLOAD 196*0Sstevel@tonic-gate 197*0Sstevel@tonic-gate # Clean-up calls D::DESTROY, B::DESTROY, A::DESTROY, C::DESTROY 198*0Sstevel@tonic-gate 199*0Sstevel@tonic-gate 200*0Sstevel@tonic-gate 201*0Sstevel@tonic-gate=head1 DESCRIPTION 202*0Sstevel@tonic-gate 203*0Sstevel@tonic-gateNEXT.pm adds a pseudoclass named C<NEXT> to any program 204*0Sstevel@tonic-gatethat uses it. If a method C<m> calls C<$self-E<gt>NEXT::m()>, the call to 205*0Sstevel@tonic-gateC<m> is redispatched as if the calling method had not originally been found. 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gateIn other words, a call to C<$self-E<gt>NEXT::m()> resumes the depth-first, 208*0Sstevel@tonic-gateleft-to-right search of C<$self>'s class hierarchy that resulted in the 209*0Sstevel@tonic-gateoriginal call to C<m>. 210*0Sstevel@tonic-gate 211*0Sstevel@tonic-gateNote that this is not the same thing as C<$self-E<gt>SUPER::m()>, which 212*0Sstevel@tonic-gatebegins a new dispatch that is restricted to searching the ancestors 213*0Sstevel@tonic-gateof the current class. C<$self-E<gt>NEXT::m()> can backtrack 214*0Sstevel@tonic-gatepast the current class -- to look for a suitable method in other 215*0Sstevel@tonic-gateancestors of C<$self> -- whereas C<$self-E<gt>SUPER::m()> cannot. 216*0Sstevel@tonic-gate 217*0Sstevel@tonic-gateA typical use would be in the destructors of a class hierarchy, 218*0Sstevel@tonic-gateas illustrated in the synopsis above. Each class in the hierarchy 219*0Sstevel@tonic-gatehas a DESTROY method that performs some class-specific action 220*0Sstevel@tonic-gateand then redispatches the call up the hierarchy. As a result, 221*0Sstevel@tonic-gatewhen an object of class D is destroyed, the destructors of I<all> 222*0Sstevel@tonic-gateits parent classes are called (in depth-first, left-to-right order). 223*0Sstevel@tonic-gate 224*0Sstevel@tonic-gateAnother typical use of redispatch would be in C<AUTOLOAD>'ed methods. 225*0Sstevel@tonic-gateIf such a method determined that it was not able to handle a 226*0Sstevel@tonic-gateparticular call, it might choose to redispatch that call, in the 227*0Sstevel@tonic-gatehope that some other C<AUTOLOAD> (above it, or to its left) might 228*0Sstevel@tonic-gatedo better. 229*0Sstevel@tonic-gate 230*0Sstevel@tonic-gateBy default, if a redispatch attempt fails to find another method 231*0Sstevel@tonic-gateelsewhere in the objects class hierarchy, it quietly gives up and does 232*0Sstevel@tonic-gatenothing (but see L<"Enforcing redispatch">). This gracious acquiesence 233*0Sstevel@tonic-gateis also unlike the (generally annoying) behaviour of C<SUPER>, which 234*0Sstevel@tonic-gatethrows an exception if it cannot redispatch. 235*0Sstevel@tonic-gate 236*0Sstevel@tonic-gateNote that it is a fatal error for any method (including C<AUTOLOAD>) 237*0Sstevel@tonic-gateto attempt to redispatch any method that does not have the 238*0Sstevel@tonic-gatesame name. For example: 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate sub D::oops { print "oops!\n"; $_[0]->NEXT::other_method() } 241*0Sstevel@tonic-gate 242*0Sstevel@tonic-gate 243*0Sstevel@tonic-gate=head2 Enforcing redispatch 244*0Sstevel@tonic-gate 245*0Sstevel@tonic-gateIt is possible to make C<NEXT> redispatch more demandingly (i.e. like 246*0Sstevel@tonic-gateC<SUPER> does), so that the redispatch throws an exception if it cannot 247*0Sstevel@tonic-gatefind a "next" method to call. 248*0Sstevel@tonic-gate 249*0Sstevel@tonic-gateTo do this, simple invoke the redispatch as: 250*0Sstevel@tonic-gate 251*0Sstevel@tonic-gate $self->NEXT::ACTUAL::method(); 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gaterather than: 254*0Sstevel@tonic-gate 255*0Sstevel@tonic-gate $self->NEXT::method(); 256*0Sstevel@tonic-gate 257*0Sstevel@tonic-gateThe C<ACTUAL> tells C<NEXT> that there must actually be a next method to call, 258*0Sstevel@tonic-gateor it should throw an exception. 259*0Sstevel@tonic-gate 260*0Sstevel@tonic-gateC<NEXT::ACTUAL> is most commonly used in C<AUTOLOAD> methods, as a means to 261*0Sstevel@tonic-gatedecline an C<AUTOLOAD> request, but preserve the normal exception-on-failure 262*0Sstevel@tonic-gatesemantics: 263*0Sstevel@tonic-gate 264*0Sstevel@tonic-gate sub AUTOLOAD { 265*0Sstevel@tonic-gate if ($AUTOLOAD =~ /foo|bar/) { 266*0Sstevel@tonic-gate # handle here 267*0Sstevel@tonic-gate } 268*0Sstevel@tonic-gate else { # try elsewhere 269*0Sstevel@tonic-gate shift()->NEXT::ACTUAL::AUTOLOAD(@_); 270*0Sstevel@tonic-gate } 271*0Sstevel@tonic-gate } 272*0Sstevel@tonic-gate 273*0Sstevel@tonic-gateBy using C<NEXT::ACTUAL>, if there is no other C<AUTOLOAD> to handle the 274*0Sstevel@tonic-gatemethod call, an exception will be thrown (as usually happens in the absence of 275*0Sstevel@tonic-gatea suitable C<AUTOLOAD>). 276*0Sstevel@tonic-gate 277*0Sstevel@tonic-gate 278*0Sstevel@tonic-gate=head2 Avoiding repetitions 279*0Sstevel@tonic-gate 280*0Sstevel@tonic-gateIf C<NEXT> redispatching is used in the methods of a "diamond" class hierarchy: 281*0Sstevel@tonic-gate 282*0Sstevel@tonic-gate # A B 283*0Sstevel@tonic-gate # / \ / 284*0Sstevel@tonic-gate # C D 285*0Sstevel@tonic-gate # \ / 286*0Sstevel@tonic-gate # E 287*0Sstevel@tonic-gate 288*0Sstevel@tonic-gate use NEXT; 289*0Sstevel@tonic-gate 290*0Sstevel@tonic-gate package A; 291*0Sstevel@tonic-gate sub foo { print "called A::foo\n"; shift->NEXT::foo() } 292*0Sstevel@tonic-gate 293*0Sstevel@tonic-gate package B; 294*0Sstevel@tonic-gate sub foo { print "called B::foo\n"; shift->NEXT::foo() } 295*0Sstevel@tonic-gate 296*0Sstevel@tonic-gate package C; @ISA = qw( A ); 297*0Sstevel@tonic-gate sub foo { print "called C::foo\n"; shift->NEXT::foo() } 298*0Sstevel@tonic-gate 299*0Sstevel@tonic-gate package D; @ISA = qw(A B); 300*0Sstevel@tonic-gate sub foo { print "called D::foo\n"; shift->NEXT::foo() } 301*0Sstevel@tonic-gate 302*0Sstevel@tonic-gate package E; @ISA = qw(C D); 303*0Sstevel@tonic-gate sub foo { print "called E::foo\n"; shift->NEXT::foo() } 304*0Sstevel@tonic-gate 305*0Sstevel@tonic-gate E->foo(); 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gatethen derived classes may (re-)inherit base-class methods through two or 308*0Sstevel@tonic-gatemore distinct paths (e.g. in the way C<E> inherits C<A::foo> twice -- 309*0Sstevel@tonic-gatethrough C<C> and C<D>). In such cases, a sequence of C<NEXT> redispatches 310*0Sstevel@tonic-gatewill invoke the multiply inherited method as many times as it is 311*0Sstevel@tonic-gateinherited. For example, the above code prints: 312*0Sstevel@tonic-gate 313*0Sstevel@tonic-gate called E::foo 314*0Sstevel@tonic-gate called C::foo 315*0Sstevel@tonic-gate called A::foo 316*0Sstevel@tonic-gate called D::foo 317*0Sstevel@tonic-gate called A::foo 318*0Sstevel@tonic-gate called B::foo 319*0Sstevel@tonic-gate 320*0Sstevel@tonic-gate(i.e. C<A::foo> is called twice). 321*0Sstevel@tonic-gate 322*0Sstevel@tonic-gateIn some cases this I<may> be the desired effect within a diamond hierarchy, 323*0Sstevel@tonic-gatebut in others (e.g. for destructors) it may be more appropriate to 324*0Sstevel@tonic-gatecall each method only once during a sequence of redispatches. 325*0Sstevel@tonic-gate 326*0Sstevel@tonic-gateTo cover such cases, you can redispatch methods via: 327*0Sstevel@tonic-gate 328*0Sstevel@tonic-gate $self->NEXT::DISTINCT::method(); 329*0Sstevel@tonic-gate 330*0Sstevel@tonic-gaterather than: 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate $self->NEXT::method(); 333*0Sstevel@tonic-gate 334*0Sstevel@tonic-gateThis causes the redispatcher to only visit each distinct C<method> method 335*0Sstevel@tonic-gateonce. That is, to skip any classes in the hierarchy that it has 336*0Sstevel@tonic-gatealready visited during redispatch. So, for example, if the 337*0Sstevel@tonic-gateprevious example were rewritten: 338*0Sstevel@tonic-gate 339*0Sstevel@tonic-gate package A; 340*0Sstevel@tonic-gate sub foo { print "called A::foo\n"; shift->NEXT::DISTINCT::foo() } 341*0Sstevel@tonic-gate 342*0Sstevel@tonic-gate package B; 343*0Sstevel@tonic-gate sub foo { print "called B::foo\n"; shift->NEXT::DISTINCT::foo() } 344*0Sstevel@tonic-gate 345*0Sstevel@tonic-gate package C; @ISA = qw( A ); 346*0Sstevel@tonic-gate sub foo { print "called C::foo\n"; shift->NEXT::DISTINCT::foo() } 347*0Sstevel@tonic-gate 348*0Sstevel@tonic-gate package D; @ISA = qw(A B); 349*0Sstevel@tonic-gate sub foo { print "called D::foo\n"; shift->NEXT::DISTINCT::foo() } 350*0Sstevel@tonic-gate 351*0Sstevel@tonic-gate package E; @ISA = qw(C D); 352*0Sstevel@tonic-gate sub foo { print "called E::foo\n"; shift->NEXT::DISTINCT::foo() } 353*0Sstevel@tonic-gate 354*0Sstevel@tonic-gate E->foo(); 355*0Sstevel@tonic-gate 356*0Sstevel@tonic-gatethen it would print: 357*0Sstevel@tonic-gate 358*0Sstevel@tonic-gate called E::foo 359*0Sstevel@tonic-gate called C::foo 360*0Sstevel@tonic-gate called A::foo 361*0Sstevel@tonic-gate called D::foo 362*0Sstevel@tonic-gate called B::foo 363*0Sstevel@tonic-gate 364*0Sstevel@tonic-gateand omit the second call to C<A::foo> (since it would not be distinct 365*0Sstevel@tonic-gatefrom the first call to C<A::foo>). 366*0Sstevel@tonic-gate 367*0Sstevel@tonic-gateNote that you can also use: 368*0Sstevel@tonic-gate 369*0Sstevel@tonic-gate $self->NEXT::DISTINCT::ACTUAL::method(); 370*0Sstevel@tonic-gate 371*0Sstevel@tonic-gateor: 372*0Sstevel@tonic-gate 373*0Sstevel@tonic-gate $self->NEXT::ACTUAL::DISTINCT::method(); 374*0Sstevel@tonic-gate 375*0Sstevel@tonic-gateto get both unique invocation I<and> exception-on-failure. 376*0Sstevel@tonic-gate 377*0Sstevel@tonic-gateNote that, for historical compatibility, you can also use 378*0Sstevel@tonic-gateC<NEXT::UNSEEN> instead of C<NEXT::DISTINCT>. 379*0Sstevel@tonic-gate 380*0Sstevel@tonic-gate 381*0Sstevel@tonic-gate=head2 Invoking all versions of a method with a single call 382*0Sstevel@tonic-gate 383*0Sstevel@tonic-gateYet another pseudo-class that NEXT.pm provides is C<EVERY>. 384*0Sstevel@tonic-gateIts behaviour is considerably simpler than that of the C<NEXT> family. 385*0Sstevel@tonic-gateA call to: 386*0Sstevel@tonic-gate 387*0Sstevel@tonic-gate $obj->EVERY::foo(); 388*0Sstevel@tonic-gate 389*0Sstevel@tonic-gatecalls I<every> method named C<foo> that the object in C<$obj> has inherited. 390*0Sstevel@tonic-gateThat is: 391*0Sstevel@tonic-gate 392*0Sstevel@tonic-gate use NEXT; 393*0Sstevel@tonic-gate 394*0Sstevel@tonic-gate package A; @ISA = qw(B D X); 395*0Sstevel@tonic-gate sub foo { print "A::foo " } 396*0Sstevel@tonic-gate 397*0Sstevel@tonic-gate package B; @ISA = qw(D X); 398*0Sstevel@tonic-gate sub foo { print "B::foo " } 399*0Sstevel@tonic-gate 400*0Sstevel@tonic-gate package X; @ISA = qw(D); 401*0Sstevel@tonic-gate sub foo { print "X::foo " } 402*0Sstevel@tonic-gate 403*0Sstevel@tonic-gate package D; 404*0Sstevel@tonic-gate sub foo { print "D::foo " } 405*0Sstevel@tonic-gate 406*0Sstevel@tonic-gate package main; 407*0Sstevel@tonic-gate 408*0Sstevel@tonic-gate my $obj = bless {}, 'A'; 409*0Sstevel@tonic-gate $obj->EVERY::foo(); # prints" A::foo B::foo X::foo D::foo 410*0Sstevel@tonic-gate 411*0Sstevel@tonic-gatePrefixing a method call with C<EVERY::> causes every method in the 412*0Sstevel@tonic-gateobject's hierarchy with that name to be invoked. As the above example 413*0Sstevel@tonic-gateillustrates, they are not called in Perl's usual "left-most-depth-first" 414*0Sstevel@tonic-gateorder. Instead, they are called "breadth-first-dependency-wise". 415*0Sstevel@tonic-gate 416*0Sstevel@tonic-gateThat means that the inheritance tree of the object is traversed breadth-first 417*0Sstevel@tonic-gateand the resulting order of classes is used as the sequence in which methods 418*0Sstevel@tonic-gateare called. However, that sequence is modified by imposing a rule that the 419*0Sstevel@tonic-gateappropritae method of a derived class must be called before the same method of 420*0Sstevel@tonic-gateany ancestral class. That's why, in the above example, C<X::foo> is called 421*0Sstevel@tonic-gatebefore C<D::foo>, even though C<D> comes before C<X> in C<@B::ISA>. 422*0Sstevel@tonic-gate 423*0Sstevel@tonic-gateIn general, there's no need to worry about the order of calls. They will be 424*0Sstevel@tonic-gateleft-to-right, breadth-first, most-derived-first. This works perfectly for 425*0Sstevel@tonic-gatemost inherited methods (including destructors), but is inappropriate for 426*0Sstevel@tonic-gatesome kinds of methods (such as constructors, cloners, debuggers, and 427*0Sstevel@tonic-gateinitializers) where it's more appropriate that the least-derived methods be 428*0Sstevel@tonic-gatecalled first (as more-derived methods may rely on the behaviour of their 429*0Sstevel@tonic-gate"ancestors"). In that case, instead of using the C<EVERY> pseudo-class: 430*0Sstevel@tonic-gate 431*0Sstevel@tonic-gate $obj->EVERY::foo(); # prints" A::foo B::foo X::foo D::foo 432*0Sstevel@tonic-gate 433*0Sstevel@tonic-gateyou can use the C<EVERY::LAST> pseudo-class: 434*0Sstevel@tonic-gate 435*0Sstevel@tonic-gate $obj->EVERY::LAST::foo(); # prints" D::foo X::foo B::foo A::foo 436*0Sstevel@tonic-gate 437*0Sstevel@tonic-gatewhich reverses the order of method call. 438*0Sstevel@tonic-gate 439*0Sstevel@tonic-gateWhichever version is used, the actual methods are called in the same 440*0Sstevel@tonic-gatecontext (list, scalar, or void) as the original call via C<EVERY>, and return: 441*0Sstevel@tonic-gate 442*0Sstevel@tonic-gate=over 443*0Sstevel@tonic-gate 444*0Sstevel@tonic-gate=item * 445*0Sstevel@tonic-gate 446*0Sstevel@tonic-gateA hash of array references in list context. Each entry of the hash has the 447*0Sstevel@tonic-gatefully qualified method name as its key and a reference to an array containing 448*0Sstevel@tonic-gatethe method's list-context return values as its value. 449*0Sstevel@tonic-gate 450*0Sstevel@tonic-gate=item * 451*0Sstevel@tonic-gate 452*0Sstevel@tonic-gateA reference to a hash of scalar values in scalar context. Each entry of the hash has the 453*0Sstevel@tonic-gatefully qualified method name as its key and the method's scalar-context return values as its value. 454*0Sstevel@tonic-gate 455*0Sstevel@tonic-gate=item * 456*0Sstevel@tonic-gate 457*0Sstevel@tonic-gateNothing in void context (obviously). 458*0Sstevel@tonic-gate 459*0Sstevel@tonic-gate=back 460*0Sstevel@tonic-gate 461*0Sstevel@tonic-gate=head2 Using C<EVERY> methods 462*0Sstevel@tonic-gate 463*0Sstevel@tonic-gateThe typical way to use an C<EVERY> call is to wrap it in another base 464*0Sstevel@tonic-gatemethod, that all classes inherit. For example, to ensure that every 465*0Sstevel@tonic-gatedestructor an object inherits is actually called (as opposed to just the 466*0Sstevel@tonic-gateleft-most-depth-first-est one): 467*0Sstevel@tonic-gate 468*0Sstevel@tonic-gate package Base; 469*0Sstevel@tonic-gate sub DESTROY { $_[0]->EVERY::Destroy } 470*0Sstevel@tonic-gate 471*0Sstevel@tonic-gate package Derived1; 472*0Sstevel@tonic-gate use base 'Base'; 473*0Sstevel@tonic-gate sub Destroy {...} 474*0Sstevel@tonic-gate 475*0Sstevel@tonic-gate package Derived2; 476*0Sstevel@tonic-gate use base 'Base', 'Derived1'; 477*0Sstevel@tonic-gate sub Destroy {...} 478*0Sstevel@tonic-gate 479*0Sstevel@tonic-gateet cetera. Every derived class than needs its own clean-up 480*0Sstevel@tonic-gatebehaviour simply adds its own C<Destroy> method (I<not> a C<DESTROY> method), 481*0Sstevel@tonic-gatewhich the call to C<EVERY::LAST::Destroy> in the inherited destructor 482*0Sstevel@tonic-gatethen correctly picks up. 483*0Sstevel@tonic-gate 484*0Sstevel@tonic-gateLikewise, to create a class hierarchy in which every initializer inherited by 485*0Sstevel@tonic-gatea new object is invoked: 486*0Sstevel@tonic-gate 487*0Sstevel@tonic-gate package Base; 488*0Sstevel@tonic-gate sub new { 489*0Sstevel@tonic-gate my ($class, %args) = @_; 490*0Sstevel@tonic-gate my $obj = bless {}, $class; 491*0Sstevel@tonic-gate $obj->EVERY::LAST::Init(\%args); 492*0Sstevel@tonic-gate } 493*0Sstevel@tonic-gate 494*0Sstevel@tonic-gate package Derived1; 495*0Sstevel@tonic-gate use base 'Base'; 496*0Sstevel@tonic-gate sub Init { 497*0Sstevel@tonic-gate my ($argsref) = @_; 498*0Sstevel@tonic-gate ... 499*0Sstevel@tonic-gate } 500*0Sstevel@tonic-gate 501*0Sstevel@tonic-gate package Derived2; 502*0Sstevel@tonic-gate use base 'Base', 'Derived1'; 503*0Sstevel@tonic-gate sub Init { 504*0Sstevel@tonic-gate my ($argsref) = @_; 505*0Sstevel@tonic-gate ... 506*0Sstevel@tonic-gate } 507*0Sstevel@tonic-gate 508*0Sstevel@tonic-gateet cetera. Every derived class than needs some additional initialization 509*0Sstevel@tonic-gatebehaviour simply adds its own C<Init> method (I<not> a C<new> method), 510*0Sstevel@tonic-gatewhich the call to C<EVERY::LAST::Init> in the inherited constructor 511*0Sstevel@tonic-gatethen correctly picks up. 512*0Sstevel@tonic-gate 513*0Sstevel@tonic-gate 514*0Sstevel@tonic-gate=head1 AUTHOR 515*0Sstevel@tonic-gate 516*0Sstevel@tonic-gateDamian Conway (damian@conway.org) 517*0Sstevel@tonic-gate 518*0Sstevel@tonic-gate=head1 BUGS AND IRRITATIONS 519*0Sstevel@tonic-gate 520*0Sstevel@tonic-gateBecause it's a module, not an integral part of the interpreter, NEXT.pm 521*0Sstevel@tonic-gatehas to guess where the surrounding call was found in the method 522*0Sstevel@tonic-gatelook-up sequence. In the presence of diamond inheritance patterns 523*0Sstevel@tonic-gateit occasionally guesses wrong. 524*0Sstevel@tonic-gate 525*0Sstevel@tonic-gateIt's also too slow (despite caching). 526*0Sstevel@tonic-gate 527*0Sstevel@tonic-gateComment, suggestions, and patches welcome. 528*0Sstevel@tonic-gate 529*0Sstevel@tonic-gate=head1 COPYRIGHT 530*0Sstevel@tonic-gate 531*0Sstevel@tonic-gate Copyright (c) 2000-2001, Damian Conway. All Rights Reserved. 532*0Sstevel@tonic-gate This module is free software. It may be used, redistributed 533*0Sstevel@tonic-gate and/or modified under the same terms as Perl itself. 534