Exporterなベースクラスのuse parent

Exporterを適用したクラスをuse parentで継承した際に、子クラスで@EXPORT*な関数を裸で参照する方法です。

# Base.pm
package Base;
use strict;
use warnings;
use parent qw(Exporter);
our @EXPORT = qw(foo);
sub new { bless +{}, shift }
sub foo { print "foo\n" }

1;

# main.pl
use strict;
use warnings;
use parent qw(Base);
BEGIN { Base->import() }

foo;

原理

まず、Exporterはimportクラスメソッドを提供します。このメソッドの中で、指定のメソッドがmixinされます。

一方、useは以下と等価です。

use Module qw(foo bar);
# は以下と等価
BEGIN { require Module; Module->import(qw(foo bar)); }

また、use parentは以下と等価です。

package Baz;
use parent qw(Foo Bar);
# は以下と等価
package Baz;
BEGIN {
    require Foo;
    require Bar;
    push @ISA, qw(Foo Bar);
}

useの時はimportが呼ばれますが、use parentではimportは呼ばれません。

以上より、use parent時には、手動でBEGINブロック内でimportを呼ぶことで、Exporterによるexportが適用できます。逆に、普通にuseして、@ISAに手動で入れてもOKです。