This is an interesting Perl behaviour. (atleast to me :) )
I have two packages PACKAGE1
and PACKAGE2
which exports function with same name Method1()
.
As there will be so many packages which will export this same function, use
-ing everything in a Perl file will be tedious. So, I have created a general include file INCLUDES.pm
which will have these use
s.
INCLUDES.pm:
use PACKAGE1;
use PACKAGE2;
1;
PACKAGE1.pm:
package PACKAGE1;
use Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw (
Method1
);
sub Method1{
print "PACKAGE1_Method1 \n";
}
1;
PACKAGE2.pm:
package PACKAGE2;
use Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw (
Method1
);
sub Method1{
print "PACKAGE2_Method1 \n";
}
1;
Tests.pl:
##################first package################
package Test1;
use INCLUDES;
my @array = values(%INC);
print "@array \n";
Method1();
##################second package################
package Test2;
use INCLUDES; #do "INCLUDES.pm";
my @array = values(%INC);
print "@array \n";
Method1();
The motive is, only the latest package's Method1()
should be used in any Perl file.
The output surprises me.
I would expect that both Method1()
calls in Tests.pl
should be success.
But only the first Method1()
executes, the second Method1()
call says "undefined".
OUTPUT:
C:/Perl/site/lib/sitecustomize.pl PACKAGE1.pm C:/Perl/lib/Exporter.pm PACKAGE2
.pmINCLUDES.pm
PACKAGE2_Method1
C:/Perl/site/lib/sitecustomize.pl PACKAGE1.pm C:/Perl/lib/Exporter.pm PACKAGE2
.pm INCLUDES.pm
Undefined subroutine &Test2::Method1 called at C:\Temp\PackageSample\Tests.pl line 15.
Do somebody have any answers/views on this?
The actual scenario:
the methods in multiple Perl modules will be having same name. But the methods from the High preference perl module should only be used.
For example, if PACKAGE1
contains Method1(), Method2()
& PACKAGE2
contains only Method1()
, then Method1()
should be used from PACKAGE2
& Method2()
should be used from PACKAGE1
Basically I want to achieve a Hierarchy among modules based on Preference. Is there any way for this?
use MyPackage
is equivalent toBEGIN{ require MyPackage; MyPackage->import }
. Inheriting from Exporter sets up animport
class method which does the function "aliasing".The problem is that you INCLUDES modules does not re-export the modules correctly. This is important because this is the process that imports the functions into the caller namespaces. While this isn't hard to craft on your own, there is a handy module for this purpose Import::Into.
Here is an example contained within a single file, it should be easy enough to reinflate into multiple, the only important difference is in the Includes module. I have made some other superficial changes but those are more for my taste.
A real world example is the module
utf8::all
which makes extensive use of this mechanism to load lots of unicode stuff into the caller package.Edit
To allow importing specific things from the
Includes
module, you could have it inherit fromExporter
as well and craft its@EXPORT
and@EXPORT_OK
to do what you mean. Otherwise, you could continue withImport::Into
and make something like bundles.Then in your test modules
In short crafting your own
import
method is not that hard, and every little is magical aboutExporter
. Once you learn about symbol table manipulation your don't need it orImport::Into
, though it is a slightly more advanced topic. Here is a question I asked about it much earlier in my Perl days: Demystifying the Perl glob (*)All that said, if object-oriented concepts of inheritance and polymorphism will do the job, you might want to investigate that route too. Here is an example of that:
See now there is no
Includes
package and no symbols are imported into theTest*
namespaces.PACKAGE2
providesMethod2
because it inherits fromPACKAGE1
and it does not override the method declaration with one of its own.In Perl,
use Module
is equivalent toBut
require
caches the list of modules that have been required. It only loads the module once per Perl process. So only the firstuse IMPORTS
does anything. Since yourIMPORTS
module doesn't have animport
method, nothing happens when youuse
it again.I'm not quite sure what you're attempting to accomplish. Perhaps your IMPORTS module should be an actual package, with an
import
method that exports whatever functions you want. That way, eachuse IMPORTS
would export functions into the package that called it.