Yes, that has advantages and disadvantages. Having seen
this done with things like Exporter.pm make me hate the
idea (nearly every module in existance inherits a dozen
utility functions from Exporter and lots of modules inherit
AUTOLOAD that supports AutoSplit and just confuses people
when they mispel a method name). Those problem don't apply
to this case, at least not yet.
One disadvantage is having to store the list of things to
export in a global array with a magic name. I prefer
something more like:
#!/usr/bin/perl -w
use strict;
use My::ProcessA( "DataType" ); # Defines: process_a() method
print DataType->process_a;
and then
package My::ProcessA;
use strict;
use ExportTo( [ qw( process_a ) ] );
sub process_a {
"Do Stuff";
}
1;
and finally
package ExportTo;
use strict;
sub import {
my( $self, $exports )= @_;
if( 2 != @_ || ! ref($exports)
|| ! UNIVERSAL::isa($exports,"ARRAY") ) {
require Carp;
Carp::croak( 'Usage: use ',__PACKAGE__,
'( [ qw( func to export ) ] )' );
}
my $caller= caller();
my $import= sub {
if( 2 != @_ ) {
require Carp;
Carp::croak( 'Usage: use ',$caller,
'( "DataType::Class" )' );
}
my( $self, $class )= @_;
for my $meth ( @$exports ) {
no strict 'refs';
*{$class."::".$meth}= \&{$caller."::".$meth};
}
};
no strict 'refs';
*{$caller."::import"}= $import;
}
1;
which ends up printing "Do stuff".
Note that I pass the list of exports to ExportTo::import as
a reference to an array because you might want to later get
fancier with the interface such as allowing My::ProcessA
to set the default class to export to. Likewise you can
enhance the closure to support more self-documenting
code like:
use My::ProcessA qw( DataType process_a revert_a );
# or even
use My::ProcessA( DataType=>[qw( process_a revert_a )] );
which I think is a great idea but that I didn't want to
get into the somewhat complex @_-handling just because
it would distract from the "point" I was making.
-
tye
(but my friends call me "Tye") |