SUPER::AUTOLOAD(@_) -- will this work? With $AUTOLOAD?

SUPER::AUTOLOAD(@_) -- will this work? With $AUTOLOAD?

am 20.12.2007 01:01:05 von el.dodgero

Him guys,

In a nutshell, I have built a module that does some database
abstraction, called SQLUtils. This object does all the database
handling and allows me to define and store named queries.

Next, I have a sort of generic Util module that uses SQLUtils and also
defines an AUTOLOAD method that lets these named queries be called as
if they were methods. Basically, you just set up your queries in a
hash, call the addQueries method which adds them all into the SQLUtils
object inside it, and if you call an undefined method it looks for the
query and, if it finds it, calls the query and fetches the result (I'm
going to add caching of results later).

Well, now I'm writing a Member module (for registered members on a
website). I want to be able to define an AUTOLOAD for that module that
will handle returning and updating member data for any member keys
that exist, calling those like methods. However, if the key does NOT
exist in the member data, I want the *other* AUTOLOAD to run. Like so:

sub AUTOLOAD {
my $obj = shift;
my $method = $AUTOLOAD;
$method =$ s/.*://;

if (exists $obj->{data}->{$method}) {
if (@_) {
my $newval = shift;
$obj->{data}->{$method} = $newval;
$obj->sql->update($newval, $obj->{data}->{id});
return $obj->{data}->{$method};
}
}
else {
$obj->SUPER::AUTOLOAD(@_);
}
}


What I'm concerned about is this: is $AUTOLOAD going to remain? Will
it be wiped to undef if I call AUTOLOAD directly?

Or am I totally barking up the wrong tree here? I've never tried this
trick before... always just used one AUTOLOAD, either the parent's or
the class's own. Never had a need to use this class's AUTOLOAD *or*
the parent class's AUTOLOAD under certain circumstances.

I mean, yeah I could just redefine all the same stuff in the parent's
AUTOLOAD inside this AUTOLOAD's else block, but that seems inelegant.

--
Dodger

Re: SUPER::AUTOLOAD(@_) -- will this work? With $AUTOLOAD?

am 20.12.2007 01:49:45 von el.dodgero

On Dec 19, 4:01 pm, Dodger wrote a question and
then shortly thereafter answered it himself.

It appears to work. I made a small test script like so:



use strict;
my $bar = new Bar;
$bar->{thing} = 1;
print "\$bar->thing = ", $bar->thing, "\n";

print "Trying Bar AUTOLOAD specifically\n";
$bar->do_bar_AUTOLOAD(1, 2, 3);
print "\n";

print "Trying inherited AUTOLOAD\n";
$bar->do_foo_AUTOLOAD(4, 5, 6);
print "\n";

package Foo;
use strict;

our $AUTOLOAD;

sub new {
my $pkg = shift;
my $class = ref $pkg || $pkg;
my $obj = {};
bless $obj, $class;
return $obj
}

sub AUTOLOAD {
my $obj = shift;
my $method = $AUTOLOAD;
$method =~ s/^.*://;
print "AUTOLOAD of Foo\n";
print "method: $method\n";
print "args: ", join('. ', @_), "\n";
}

package Bar;
use strict;
use vars('@ISA');
BEGIN {
push @ISA,('Foo');
}

our $AUTOLOAD;


sub AUTOLOAD {
my $obj = shift;
my $method = $AUTOLOAD;
$method =~ s/.*://;
print "method: $method\n";

if ($method eq 'do_bar_AUTOLOAD') {
print "AUTOLOAD of Bar\n";
print "method: $method\n";
print "args: ", join('. ', @_), "\n";
}
elsif (exists $obj->{$method}) {
return "(Bar sez) $obj->{$method}";
}
else {
$obj->SUPER::AUTOLOAD(@_);
}
}

and my results came back as:

method: thing
$bar->thing = (Bar sez) 1
Trying Bar AUTOLOAD specifically
method: do_bar_AUTOLOAD
AUTOLOAD of Bar
method: do_bar_AUTOLOAD
args: 1. 2. 3

Trying inherited AUTOLOAD
method: do_foo_AUTOLOAD
AUTOLOAD of Foo
method:
args: 4. 5. 6

method: DESTROY
AUTOLOAD of Foo
method:
args:


So it appears that this trick will not work unless I specifically
assign to Foo::AUTOLOAD before calling it...

I tried it two ways:
else {
$SUPER::AUTOLOAD = $AUTOLOAD;
$obj->SUPER::AUTOLOAD(@_);
}
does NOT work, which seems odd...

because

else {
$Foo::AUTOLOAD = $AUTOLOAD;
$obj->SUPER::AUTOLOAD(@_);
}

DOES work...

So, I know how to do it now, but... I'm still unclear on one part...

Can anyone explain why I can't set the $AUTOLOAD in Foo with
$SUPER::AUTOLOAD instead of $Foo::AUTOLOAD if I can successfully call
SUPER::AUTOLOAD() instead of having to specify Foo::AUTOLOAD() ?