如何创建为用户导入许多模块的模块?

时间:2010-08-19 18:00:42

标签: perl module

我在Perl中实现了一个相当复杂的数据结构。这已被分解为大约20个班级。基本上,只要你想使用其中一个类,就需要使用它们。

现在,如果有人想要使用这种数据结构,他们需要做类似的事情:

use Component::Root;
use Component::Foo;
use Component::Bar;
use Component::Baz;
use Component::Flib;
use Component::Zen;
use Component::Zen::Foo;
use Component::Zen::Bar;
use Component::Zen::Baz;
... # 15 more of these...
use Component::Last;

能够操纵它的所有部分。如何编写一个为用户执行此操作的模块,因此他们所要做的只是

use Component;

导入所有其他模块?

在这种特殊情况下,模块都是类,没有导出。

5 个答案:

答案 0 :(得分:6)

如果这些只是类(即当它们use时它们不导出任何函数或变量),那么真正重要的是它们已被加载。

只需创建Component.pm

package Component;

our $VERSION = '1.00';

use Component::Root;
use Component::Foo;
use Component::Bar;
use Component::Baz;
use Component::Flib;
use Component::Zen;
use Component::Zen::Foo;
use Component::Zen::Bar;
use Component::Zen::Baz;
... # 15 more of these...
use Component::Last;

1; # Package return value

您不需要Exporter或类似内容。

然而,将这些use语句放入根节点的类或创建的use语句中,可能更有意义,而不是只有use Component::Root; my $root = Component::Root->new(...); 语句的模块。数据结构。也就是说,人们会想说:

use Component qw(build_structure);
my $root = build_structure(...);

use Component;
my $root = Component::Root->new(...);

取决于您的数据结构的正常创建方式。人们写作可能有点令人困惑:

new

但它实际上取决于您的API的样子。如果有许多人可能正在调用use Component,那么{{1}}可能是最佳选择。

答案 1 :(得分:1)

  • 您可以对 export_to_level的所有软件包使用Exporter方法。

    MyPackage->export_to_level($where_to_export, $package, @what_to_export);
    
  • 您也可以导出导入的所有符号。

    use PackageA qw<Huey Dewey Louie>;
    ...
    our @ISA = qw<Exporter>; #inherit Exporter
    our @EXPORT = qw<Huey Dewey Louie>;
    
  • 但是,如果您不想导出任何符号,并且只想加载模块,那么只需在上面包含那些use语句,并在其中包含任何包进程将能够将它们实例化为类,比如它们都是OO模块。

    如果它们已成功加载,它们将存在于%INC和符号表中。

答案 2 :(得分:0)

Moose::Exporter似乎是这样做的,尽管你所有其他模块也必须使用它。

Component

Moose::Exporter->setup_import_methods(
    also => [qw/Component::Root Component::..*/],
);

答案 3 :(得分:0)

如果模块没有导出任何东西并且没有导入方法(与cjm的答案相同的要求),你只需要加载模块而不需要导入:

package Component;

our $VERSION = '1.00';

require Component::Root;
require Component::Foo;
require Component::Bar;
require Component::Baz;
require Component::Flib;
require Component::Zen;
require Component::Zen::Foo;
require Component::Zen::Bar;
require Component::Zen::Baz;
... # 15 more of these...
require Component::Last;

1; # Package return value

模块的用户只会这样做:

require Component;

但是,如果某些模块执行导出,则必须调用其import方法。因此,您需要在import模块中添加一个Component方法来调用它们:

sub import
{
    Component::Root->import;
    Component::Foo->import;
    ...
}

所以模块用户必须use

use Component;

请注意,如果导入的模块必须在导入器的上下文中插入符号,则可能必须使用其他一些技巧。例如,参见POE's import如何做到这一点。

答案 4 :(得分:0)

Modern::Perl模块自称“使用一个命令启用Modern Perl的所有功能”,其中该命令为

use Modern::Perl;

并且这些功能

  

目前,这只启用了strict和warnings pragma,以及Perl 5.10中提供的所有功能。它还启用C3方法解析顺序;请参阅perldoc mro以获得解释。

对于一行代码来说,这很多,根据perlmod documentation完全等同于

BEGIN { require Module; import Module; }

考虑Modern :: Perl的implementation

package Modern::Perl;

our $VERSION = '1.03';

use 5.010_000;

use strict;
use warnings;

use mro     ();
use feature ();

sub import {
    warnings->import();
    strict->import();
    feature->import( ':5.10' );
    mro::set_mro( scalar caller(), 'c3' );
}

1; # End of Modern::Perl

根据您的情况,从您的顶级模块use调整您想要加载的所有其他模块,并从MyTopLevelModule::import调用其导入(如果有)。

请注意,您不一定需要复制

use 5.010_000;

进入MyTopLevelModule.pm,但这是一个好主意!根据{{​​3}}:

  

在特殊的use VERSION形式中, VERSION 可以是正小数,例如5.006,将与$]进行比较,或者是v -v5.6.1形式的字符串,将与$^V(又名$PERL_VERSION)进行比较。如果 VERSION 大于当前Perl解释器的版本,则会引发异常; Perl不会尝试解析文件的其余部分。与require比较,{{1}}可以在运行时进行类似的检查。