http://www.perlmonks.org?node_id=412388

Fellow Monks,

Today I encountered some issue trying to use Object inheritance and AUTOLOAD at the same time.

Let me explain : Let's say we have a Dog class, of which a Husky class inherits. AUTOLOAD is used to managed simple attributes, for exampe for setting and getting.

Now there are some attributes that should be managed by AUTOLOAD in the Dog class, and some specific attributes that should be in the Husky class. That raises the problem : AUTOLOAD is only called once, from the package the objects belongs to. There is not AUTOLOAD automatic inheritance.

Easy, will you say, let's call parent AUTOLOAD. Ok, by one must take care of the fact the scalar $AUTOLOAD is only defined in the object package.

So, to make it work, I finally wrote the code below. The idea is really simple, and I guess I may be reinventing the wheel, but anyway... Husky AUTOLOAD is as expected, but finally calls Dog's AUTOLOAD. Dog AUTOLOAD takes care of the fact that it could be called in two ways : either directly, if we have a Dog object, or from Husky AUTOLOAD. Comments are welcome...

# # Parent Object Dog # package Dog; use vars qw/$AUTOLOAD/; sub AUTOLOAD { my ($self, $autoload) = @_; my @attributes = qw / bone /; my $attr = $AUTOLOAD; # If called through Husky, retrieve the original $AUTOLOAD $attr ||= $autoload; $attr =~ s!(.*?)::!!; return unless $attr =~ /[^A-Z]/; # Get rid of DESTROY if ($attr =~ m!get_(.*)! and grep { /^$1$/ } @attributes) { print "Bonga\n"; return $self->{$1}; } } sub new { my $class = shift; return bless {}, $class; } # # Object Husky, A Husky is a Dog ;) # package Husky; #=pod use vars qw/$AUTOLOAD/; sub AUTOLOAD { my $self = shift; my @attributes = qw / eyes /; my $attr = $AUTOLOAD; $attr =~ s!(.*?)::!!; return unless $attr =~ /[^A-Z]/; # Get rid of DESTROY if ($attr =~ m!get_(.*)! and grep { /^$1$/ } @attributes) { print "Bongo\n"; return $self->{$1}; } $self->SUPER::AUTOLOAD($AUTOLOAD); } #=cut use base 'Dog'; # # Main package # package Main; my $billou = new Husky; print "Get bone : \n"; $billou->get_bone; print "Get eyes : \n"; $billou->get_eyes;

--
zejames

Replies are listed 'Best First'.
Re: Object inheritance and AUTOLOAD
by gaal (Parson) on Dec 04, 2004 at 12:06 UTC
    If you want to chain AUTOLOADs, take a look at NEXT.pm. But if all you need this for is accessors, you're better off using one of the accessor modules from CPAN; my favorite is Class::Accessor. It's faster and plays nicely with inheritance.
Re: Object inheritance without AUTOLOAD
by diotalevi (Canon) on Dec 04, 2004 at 16:42 UTC

    You would have been better just avoiding AUTOLOAD and generating your functions at compiletime. Not only will this mean you don't have to write a custom ->can, it means that when someone else is debugging this that they won't be confused by functions that only exist after they have been called, that code analysis tools ( all kinds of things in B:: and Devel:: ) are going to work instead of having to just punt, etc.

    You should only be using AUTOLOAD like this if you have a real and quantifiable benefit. I recall some code of BrowserUK's that would be a great candidate for AUTOLOAD. That situation involved some hundreds of packages where only a small fraction would ever be used at one time. This isn't true for any code I've seen anyone else ever post. In fact, BrowserUK's example was the only time I've seen there being any benefit to using AUTOLOAD.

    package Dog; BEGIN { my @attributes = qw/ bone /; for my $attribute ( @attributes ) { no strict 'refs'; *{"get_$attribute"} = sub { ... }; *{"set_$attribute"} = sub { ... }; } }
      I see that you don't read my posts. :-P

      For an idea of what Larry Wall planned on using AUTOLOAD for, see Shell.

      But that said, I agree that AUTOLOAD is a sledgehammer not to be used lightly. However I'd disagree with you on whether you need to use a custom can if you use AUTOLOAD. See Why breaking can() is acceptable for a fuller explanation of my views.

        Oh ok fine. I use Shell myself but rarely if ever think of it. So you got me. There are other uses for AUTOLOAD than I mentioned and the ones you mentioned are actually useful. I was thinking of the common use of AUTOLOAD to delay method generation. Its that practice that I see is completely out of whack and that I'm thinking of when I complain about people who use AUTOLOAD.

        It also occurs to me that using AUTOLOAD in the way I actually complained about exerts addition runtime penalties that would not normally exist - the entire method cache is invalided whenever the newly generated function is assigned into place.