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

package A; use Data::Dumper; package B; use strict; use base 'A'; print Dumper([1]);
The above example does not work as namespaces are not inherited, and @ISA is not checked unless arrow notation is used (e.g. $foo->Dumper(1), which would result in $foo being passed as well).

Is there a clean way to automagically inherit the subs from 'A' when you use it as a base? i.e. Not using Exporter and EXPORT|EXPORT_OK.

The only thing that I came up with that would allow a lazy inheritance of subs from the namespace of @ISA is:
sub AUTOLOAD { our (@ISA, $AUTOLOAD); use Symbol; my ($my_package,$method) = $AUTOLOAD =~ /^(.*)::(.*?)$/; for my $base (@ISA) { my $ref = qualify_to_ref($method,$base); next unless $ref && *{$ref}{CODE}; # $method exists as a sub in $base. my $new_glob = qualify_to_ref($method,$my_package); # Copy the code reference from the base class to this one *$new_glob = *{$ref}{CODE}; # Magic goto so AUTOLOAD doesn't appear in the caller list goto &$new_glob; } use Carp 'croak'; croak("Invalid method $method"); }

Replies are listed 'Best First'.
Re: use base and inheritance of non-method subroutines
by perrin (Chancellor) on Dec 30, 2005 at 21:31 UTC
    The bottom line is that the Perl approach to importing subs is not really compatible with OO. If you want to be able to inherit things, don't use importing and always call them as methods, not subs. Hacks to get around this juat add to the mess.
Re: use base and inheritance of non-method subroutines
by diotalevi (Canon) on Dec 30, 2005 at 21:46 UTC

    You're blowing your method cache whenever that AUTOLOAD function runs. You're also abusing OO to avoid using Exporter::import. Just write it out the proper way and it'll all work out fine.

    ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

Re: use base and inheritance of non-method subroutines
by merlyn (Sage) on Dec 30, 2005 at 23:58 UTC
    Your subject line is flawed. There is no "inheritance of non-method subroutines". You'll need to rethink what you're trying to do... are you wanting to import things, or to inherit things?

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

Re: use base and inheritance of non-method subroutines
by gam3 (Curate) on Dec 31, 2005 at 04:38 UTC
    While I don't think that there is a general solution to this problem. Here is an expample of a very hard case.
    package A; use Data::Dumper (); sub Dumper { print "This is not dumper\n"; }
    However if you make some assumptions you can get something that works (or gets close to it).
    package ibase; BEGIN { require base; *{"_import"} = \&{"base::import"}; for (qw( )) { *{"$_"} = \&{"base::$_"}; } } our $ExportLevel = 0; sub import { my $self = shift; my $callpkg = caller($ExportLevel); eval { $self->_import(@_); }; for my $key (keys %INC) { if ($key =~ m|Data/Dumper.pm|) { *{"$callpkg\::Dumper"} = \&{"Data::Dumper::Dumper"}; } } } 1;
    Then use ibase rather than base.
    package A; use Data::Dumper; print Dumper \%INC, \@INC; package B; use strict; use ibase 'A'; print Data::Dumper::Dumper(\%A::INC, \%INC); print Dumper([1]);
    You code make this a little more robust buy using @EXPORT_OK to see what all should be imported.
    -- gam3
    A picture is worth a thousand words, but takes 200K.