Since you are writing object-oriented perl, it is a very bad idea to import symbols from one package into another. The inheritance the Perl's standard mechanism will work fine, and all you seem to be doing here is renaming the imported methods.
The problem is that use parent
doesn't call the other package's import
routine, so build_gmorn
is never imported into mB
as gmorn
.
In addition, as your error message says, gmorn
is not exported by the mB
module, so it cannot be imported into mFr
.
If you change mB
to look like this then your code will mostly work. Note that because there is no mA.pm
I have had to write mA->import('gmorn')
as the correct use mA 'gmorn'
would fail.
package mB;
mA->import('gmorn');
use parent -norequire, 'mA';
use Sub::Exporter -setup => {
exports => {
gmorn => undef,
gnite => \&build_gnite
}
};
sub build_gnite {
my ( $class, $name, $arg ) = @_;
return sub { say "$arg->{salutation}"; }
}
Update
There is no way to get the parameters to use Sub::Exporter
to "pass through" multiple levels of use
, because the import
subroutine needs to call the generator function. So in your example mB::import
needs to call mA::build_gmorn
but it has no knowledge of that subroutine so it cannot be done.
The only convenient solution is to export both the generator and a generated subroutine, so that the calling code can either use the function or export a generated function itself.
This set of programs works fine.
mA.pm
use 5.010;
use warnings;
package mA;
use Sub::Exporter -setup => {
exports => [
'build_gmorn',
gmorn => \&build_gmorn,
]
};
sub build_gmorn {
my ( $class, $name, $arg ) = @_;
return sub { say "$arg->{salutation}"; }
}
1;
mB.pm
use 5.010;
use warnings;
package mB;
use mA qw/ gmorn build_gmorn /;
use parent 'mA';
use Sub::Exporter -setup => {
exports => [
'build_gmorn',
gmorn => \&build_gmorn,
'build_gnite',
gnite => \&build_gnite
]
};
sub build_gnite {
my ( $class, $name, $arg ) = @_;
return sub { say "$arg->{salutation}"; }
}
1;
mFr.pl
use 5.010;
use warnings;
package mFr;
use parent 'mB';
mB->import(
gmorn => { salutation => 'Bon Jour' },
gnite => { salutation => 'Bon Nuit' }
);
sub new { return bless {}, shift }
my $obj = mFr->new;
$obj->gmorn();
$obj->gnite();
output
Bon Jour
Bon Nuit