AUTOLOAD plus instance methods

D

Dan Rawson

I have a tiny class (copied almost verbatim from the perltoot pages) which has some AUTOLOAD methods plus one other.
When I run the attached, it dies with "Can't access DESTROY field . . . ." at the very end. What am I doing wrong??

TIA . . . .

Dan


#!/usr/bin/env perl -w
package myTest;
use Carp;

our $AUTOLOAD;
use strict;
my %config = (
recursive => 0, # Bool
overwrite => 0, # Bool
);

sub new()
{
my $class = shift;
my $self = {
_permitted => \%config,
%config,
};
bless $self, $class;
return $self;
}

sub AUTOLOAD()
{
my $self = shift;
my $type = ref($self) || die;
my $name = $AUTOLOAD;
$name =~ s/.*://;
unless (exists $self->{_permitted}->{$name})
{
croak "Can't access $name field in object of class $type";
};
if (@_)
{
return $self->{$name} = shift;
}
else
{
return $self->{$name}
}

}

sub show_config()
{
my $self = shift;
print "Recursive: ".($self->recursive() ? "True" : "False")."\n";
print "Over-write: ".($self->overwrite() ? "True" : "False")."\n";

}
1;

package MAIN;

my $fred = myTest->new();
my $mary = myTest->new();

$mary->recursive(1);
$mary->show_config();
 
J

JS Bangs

Dan Rawson sikyal:
I have a tiny class (copied almost verbatim from the perltoot pages)
which has some AUTOLOAD methods plus one other. When I run the attached,
it dies with "Can't access DESTROY field . . . ." at the very end.
What am I doing wrong??

This is a common problem--I've run into it myself.

Perl calls a method named DESTROY() on all objects when they're garbage
collected, with special magic to ensure that if this method doesn't exist
no errors are generated. However, before that happens the DESTROY gets
caught in the AUTOLOAD method, and so generates this message.

There's two ways to fix this:
sub AUTOLOAD()
{
my $self = shift;
my $type = ref($self) || die;
my $name = $AUTOLOAD;
$name =~ s/.*://;

Here you could add something like:

return if $name eq 'DESTROY';
unless (exists $self->{_permitted}->{$name})
{
croak "Can't access $name field in object of class $type";
};
if (@_)
{
return $self->{$name} = shift;
}
else
{
return $self->{$name}
}

}

Or you could add

sub DESTROY {}

This means that DESTROY does exist (but does nothing), so it never enters
the AUTOLOAD routine.


--
Jesse S. Bangs (e-mail address removed)
http://students.washington.edu/jaspax/
http://students.washington.edu/jaspax/blog

Jesus asked them, "Who do you say that I am?"

And they answered, "You are the eschatological manifestation of the ground
of our being, the kerygma in which we find the ultimate meaning of our
interpersonal relationship."

And Jesus said, "What?"
 
S

Steven Kuo

I have a tiny class (copied almost verbatim from the perltoot
pages) which has some AUTOLOAD methods plus one other. When I run
the attached, it dies with "Can't access DESTROY field . . . ." at
the very end. What am I doing wrong??

TIA . . . .

Dan


perltoot does describe DESTORY as the destructor used by perl. Your
AUTOLOAD subroutine is intercepting this call. You can either
define a DESTROY subroutine in your package (see below):
#!/usr/bin/env perl -w
package myTest;
use Carp;

our $AUTOLOAD;
use strict;
my %config = (
recursive => 0, # Bool
overwrite => 0, # Bool
);

sub new()
{
my $class = shift;
my $self = {
_permitted => \%config,
%config,
};
bless $self, $class;
return $self;
}



sub DESTORY { } # do nothing


sub AUTOLOAD()
{
my $self = shift;
my $type = ref($self) || die;
my $name = $AUTOLOAD;
$name =~ s/.*://;


# or handle DESTORY within AUTOLOAD:

return if $name eq 'DESTROY';
unless (exists $self->{_permitted}->{$name})
{
croak "Can't access $name field in object of class $type";
};
if (@_)
{
return $self->{$name} = shift;
}
else
{
return $self->{$name}
}

}

(remainder snipped)
 
D

Dan Rawson

OK, thanks . . . .

JS said:
Dan Rawson sikyal:




This is a common problem--I've run into it myself.

Perl calls a method named DESTROY() on all objects when they're garbage
collected, with special magic to ensure that if this method doesn't exist
no errors are generated. However, before that happens the DESTROY gets
caught in the AUTOLOAD method, and so generates this message.

There's two ways to fix this:




Here you could add something like:

return if $name eq 'DESTROY';




Or you could add

sub DESTROY {}

This means that DESTROY does exist (but does nothing), so it never enters
the AUTOLOAD routine.


--
Jesse S. Bangs (e-mail address removed)
http://students.washington.edu/jaspax/
http://students.washington.edu/jaspax/blog

Jesus asked them, "Who do you say that I am?"

And they answered, "You are the eschatological manifestation of the ground
of our being, the kerygma in which we find the ultimate meaning of our
interpersonal relationship."

And Jesus said, "What?"
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,071
Latest member
MetabolicSolutionsKeto

Latest Threads

Top