12.10 Exporting in a Primarily OO Module

As seen earlier, the normal means of using an object-oriented module is to call class methods and then methods against instances resulting from constructors of that class. This means that an OO module typically exports nothing, so you'll have:

package My::OOModule::Base;
our @EXPORT = (  ); # you may even omit this line
use Exporter;
our @ISA = qw(Exporter);

As stated in Chapter 8, you can even shorten this down:

package My::OOModule::Base;
use base qw(Exporter);

What if you then derive a class from this base class? The most important thing to remember is that the import method must be defined from the Exporter class, so you add it like so:

package My::OOModule::Derived;
use base qw(Exporter My::OOModule::Base);

However, wouldn't the call to My::OOModule::Derived->import eventually find its way up to Exporter via My::OOModule::Base? Sure it would. So you can leave that out:

package My::OOModule::Derived;
use base qw(My::OOModule::Base);

Only the base classes at the top of the tree need specify Exporter and only when they derive from no other classes.

Please be aware of all the other reserved method names that can't be used by your OO module (as described in the Exporter manpage). At the time of this writing, the list is export_to_level, require_version, and export_fail. Also, you may wish to reserve unimport because that routine will be called by replacing use with no. That use is rare for user-written modules, however.

Even though an OO module typically exports nothing, you might choose to export a named constructor or management routine. This routine typically acts a bit like a class method but is meant to be called as a normal routine.

One example can be found in the LWP library (on the CPAN). The URI::URL module (now deprecated and replaced by the URI module) deals with universal resource identifiers, most commonly seen as URLs such as http://www.gilligan.crew.hut/maps/island.pdf. You can construct a URI::URL object as a traditional object constructor with:

use URI::URL;
my $u = URI::URL->new("http://www.gilligan.crew.hut/maps/island.pdf");

The default import list for URI::URL also imports a url subroutine, which can be used as a constructor as well:

use URI::URL;
my $u = url("http://www.gilligan.crew.hut/maps/island.pdf");

Because this imported routine isn't a class method, you don't use the arrow method call to invoke it. Also, the routine is unlike anything else in the module: no initial class parameter is passed. Even though normal subroutines and method calls are both defined as subroutines in the package, the caller and the author must agree as to which is which.

The url convenience routine was nice, initially. However, it also clashed with the same-name routine in CGI.pm, leading to interesting errors (especially in a mod_perl setting). (The modern interface in the URI module doesn't export such a constructor.) Prior to that, in order to prevent a crash, you had to remember to bring it in as:

use URI::URL (  );        # don't import "url"
my $u = URI::URL->new(...);