hackdaddy has asked for the wisdom of the Perl Monks concerning the following question:

I have a method that uses AUTOLOAD to access class data. However when I use the second call below I get an error about strict refs. How do I modify my AUTOLOAD method to handle the second class method call?
$package = $self->{_archive_tbl}->get_pkgname; $package = WM::Install::Table::ArchiveTbl->get_pkgname();
Can't use string ("WM::Install::Table::ArchiveTbl") as a HASH ref while "strict refs" in use at /u08/pkg/wms/wmcmtools/modules/WM/Install/Table/ArchiveTbl.pm line 192.
sub AUTOLOAD { my ($self, $newval) = @_; $AUTOLOAD =~ /.*::get(_\w+)/ and $self->_accessible($1) and return $self->{$1}; $AUTOLOAD =~ /.*::_set(_\w+)/ and $self->_accessible($1) and do { $self->{$1} = $newval; return; }; # error croak "No such method: $AUTOLOAD"; }

Replies are listed 'Best First'.
(Ovid) Re: Autoload'ed class method calls
by Ovid (Cardinal) on Apr 05, 2002 at 18:15 UTC

    The easy way to explain this is to consider a typical constructor.

    sub new { my $class = shift; my $data = {}; bless $data, $class; return $data; }

    Now, why is the first argument to the constructor called $class instead of $self? Because when the constructor is called properly, the first argument to it is the name of the class (as a string), not an object. This is because you haven't created the object yet!

    $package = WM::Install::Table::ArchiveTbl->get_pkgname();

    The previous line of code cannot work with the current structure of your AUTOLOAD because the first argument will be the classname and not a hashref. Either call the method from an instance of the class or recode your AUTOLOAD.

    Cheers,
    Ovid

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

      Ovid, not sure that hackdaddy has got it wrong. His code is the AUTOLOAD sub, not the constructor. I presume he will be supplying his own new sub so that AUTOLOAD will not be called on construction.

      More importantly, he needs to declare $AUTOLOAD in package namespace, with

      use vars qw($AUTOLOAD);
      or
      our $AUTOLOAD;
      The rest seems to go through use strict 'refs'OK.

      Update: Ovid I am humbled! It's interesting how staring at a piece of code can lead you to wrong conclusions (in my case exacerbated by lack of sleep and coffee).

      It also shows what a snarfy beast AUTOLOAD can be. I've written pseudo-methods in AUTOLOAD myself, but usually solved problems like hackdaddy's by stepping through with the debugger.

        Read through his code and error message again. hackdaddy already has $AUTOLOAD declared properly, otherwise the first method call would fail, but according to hackdaddy, it's successful. However, read through the text of the actual error message.

        Can't use string ("WM::Install::Table::ArchiveTbl") as a HASH ref whil +e "strict refs" in use at /u08/pkg/wms/wmcmtools/modules/WM/Install/Table/ArchiveTbl.pm line +192.

        Now look at first few lines of the autoload.

        sub AUTOLOAD { my ($self, $newval) = @_; $AUTOLOAD =~ /.*::get(_\w+)/ and $self->_accessible($1) and return $self->{$1};

        As you can see, the return statement (return $self->{$1}) is attempting to use $self as a hashref. Since the error messsage shows that the programmers is trying to use the package name as a hashref, we clearly have the package name and not the object being passed as the first argument to AUTOLOAD. I was using a generic constructor to illustrate how the first argument could be a package name instead of an object, as expected.

        Cheers,
        Ovid

        PS: I'm also a Terry Pratchett fan (I'm assuming that's what your nick refers to).

        Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

Re: Autoload'ed class method calls
by strat (Canon) on Apr 06, 2002 at 15:20 UTC