If I have a module with methods a
and b
and want to export them I do:
use Exporter;
our @ISA = qw (Exporter);
our @EXPORT = qw (a b);
What I don't understand is what does this line:our @ISA = qw (Exporter);
do?
The @Foo::ISA
array is a global variable that holds the classes from which class Foo
inherits.
Generally, you shouldn't manipulate @ISA
directly; doing so is a sign that you're probably looking at old Perl code.
If you want to declare an inheritance relationship, a better way to do it is
use parent 'Exporter';
which tweaks @ISA
behind the scenes for you and also does some other useful stuff.
In your case, when you do
our @ISA = qw(Exporter)
you're declaring your class as a subclass of Exporter
. The Exporter
class provides a method called import
. Why do you want that? Because when you say
use MyClass;
What actually happens is:
BEGIN {
require 'MyClass.pm';
MyClass->import;
};
The import
method is automatically called every time someone use
s your class. That method can do anything you want. (You could write your own import
if you want to) but usually it's used to import symbols into the caller's namespace. That's what Exporter
does for you.
However, Exporter
also exports its own import
method, so you don't actually have to inherit it any more. (This was fixed a loooong time ago.) So now you can just say
use Exporter qw(import);
and your package will get the import
method without having to mess with @ISA
at all.
Think object oriented here.
Think of Exporter not as a mere module, but as a class. Think of ISA
as meaning "Is a" as in "My module is a sub-class of Exporter".
What you're doing is declaring your module as a sub-class of the Exporter class which means you can use the import
method of the Exporter class which is sort of useful.
To really explain what Exporter is doing, you must understand that Perl uses Namespaces. Imagine if your program has a variable1 called $total
, but so does the module you're using. Your $total
variable would interfere with the module's $total
variable.
To prevent this, Perl uses namespaces. Your program operates in the default namespace of main
. Your modules use the package
function to declare a new namespace. Now, both you and your module can safely use a variable called $total
. In your program, it's really $main::total
, and in the package, it's $Package::Name::total. If you want to use something from one _namespace_ in another, you can prepend the _namespace_ on it. Think of the
$File::Find::nameand
$File::Find::dirvariables you have when you use
File::Find`.
What the Exporter's import
method does is copy your subroutines (and if you so desire, your variables) from your namespace to the current namespace. Imagine using the File::Copy
module without the ability to copy over the copy
subroutine to your main namespace. You could still use it, but you'd have to give it the name of the namespace on it:
use File::Copy;
...
File::Copy::copy( $from_file, $to_file );
Thanks to Exporter (and the import method), any subroutines you put into your packages @EXPORT
array are copied over to the current namespace. Thus, you can access File::Copys
copy` subroutine like this:
use File::Copy;
...
copy ( $from_file, $to_file );
This is also why you must declare all of these variables as our
and not my
. my
variables are lexically scoped and cannot be accessed outside of where they're declared. Package variables (like $File::Find::name
) can be. For Exporter
to find your @EXPORT
, and @EXPORT_OK
arrays, these need to be package variables.
Now, comes the desirability of exporting functions...
The oldest modules that we know and love export subroutines willy-nilly. You use File::Copy, File::Path, File::Find, and you have immediate access to their subroutines. This is because they put their subroutines into the @EXPORT
array. This was at one time thought desirable because it makes these functions immediately available to you.
Newer modules like File::Temp
require you to declare the subroutines you want to import:
use File::Temp qw(tempdir);
...
my $temp_dir = tempdir;
If I didn't have that qw(tempdir)
, I couldn't use the tempdir
function.
This is considered polite. The module is asking your permission to import the function. This is done by putting the subroutines into @EXPORT_OK
. These will only be exported upon request.
This is better because you don't have to import everything, just what you need. And, you're documenting where these functions are defined.
Object Oriented modules don't export anything at all and don't need to use Exporter. It's been a long time since I've written a module that uses Exporter.
-- 1 We're talking about package variables here. Package variables are visible everywhere.
The @ISA
package variable is used to specify inheritance between classes. You are discouraged to manipulate this variable yourself. If you want to inherit from another class, do
use parent 'Parent::Class';
or pre v10.1:
use base 'Parent::Class';
In this specific case, inheriting from Exporter
makes the import
method available. Your code could be rewritten as.
use parent 'Exporter';
our @EXPORT = qw/a b/;
The import
method is called automatically when your module is use
d, and may export symbols to the using package.
Why using @ISA
manually is bad:
Do not assign to @ISA
: Other modules may have already added entries to it; this would overwrite them. Therefore, push @ISA, "Some::Class"
.
Avoid modifying @ISA
during runtime. It is better to specify the inheritance relationship as early as possible (during parsing or after initial compilation), so that your module could be used there without restrictions. You could wrap it in an BEGIN
or CHECK
block, like
BEGIN {
push @ISA, "Some::Class";
}
Inheritance via parent
makes this much easier. parent
will also compile the requested module if it isn't already loaded: no need for use Some::Class
.
It instructs Perl to look in the Exporter
module for methods when it can't find them in your package. The usual method you want to inherit from Exporter
is its import
method, which is where the work of copying your module's exported symbols to the calling package takes place.
From perlobj
:
Each package contains a special array called
@ISA
. The@ISA
array contains a list of that class's parent classes, if any. This array is examined when Perl does method resolution, which we will cover later.
For example, this is an error because Perl will try to call the non-existent subroutine Foo::some_method
:
sub Bar::some_method { 42 }
my $obj = bless {}, 'Foo';
$obj->some_method;
The @ISA
variable in a package tells Perl to look for the method in other packages, so this code will work and invoke the Bar::some_method
method.
sub Bar::some_method { 42 }
my $obj = bless {}, 'Foo';
@Foo::ISA = qw(Bar);
$obj->some_method;
The practical application for this is inheritance.
As amon mentions, there is rarely a need to set @ISA
directly. The parent
pragma (and the older, now discouraged base
pragma) declare inheritance relationships and set this variable for you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With