2010-01-08 54 views
4

我有一个数字,我从下载数据和按摩到其他格式(使用Perl)在工作中使用不同的站点,都办起一个Perl脚本还挺像这样的:如何查找从Perl中的包继承的所有包?

#! /usr/bin/perl 
use strict; 

use My::Package1; 
use My::Package2; 

my $p1 = My::Package1->new; 
$p1->download; 

my $p2 = My::Package2->new; 
$p2->download; 

等等等。目前,每个My::Package是它自己的包;它不会从基本包或任何东西继承。我打算使用Moose重新编写它们,我希望在每次添加新软件包时都不必编辑运行下载的Perl脚本,而是可能有一种方法可以找到从基本软件包继承的软件包,然后在一个循环实例每做下载,有点像这样:

#! /usr/bin/perl 
use strict; 

for my $pname (packages_that_inherit_from("My::Package")) { 
    my $package = $pname->new; 
    $package->download; 
} 

是吗,什么ILKE它,可能吗?

TIA

+1

为什么不提供一个配置文件来使用软件包的名称? – 2010-01-08 03:26:11

+0

我想避免不得不将新包添加到另一个文件,无论是perl脚本还是配置文件。 – Mark 2010-01-08 03:50:41

回答

2

你所要求的不会是可能的,因为没有你正在寻找使用的软件包将尚未加载。为什么不把所有的软件包放在一个公共目录中,然后让你的脚本打开该目录,并为每个文件都要求它,然后实例化你的对象。

1

基于继承,没有办法做到这一点,因为父类甚至不知道它是否具有后代,不必介意它有多少或它们的名字是什么。

use Module::Pluggable require => 1, search_path => ['Parent']; 
my @descendants = plugins(); 

但是,如果按照使用分层命名空间和命名的后裔为Parent::FooParent::Bar等的共同约定,您可以通过使用Module::Pluggable加载了Parent命名空间下的一切接近这个

因为这是基于命名空间的,所以它会拉动Parent::Helper::ThatIsNotAChild,而错过Child::NotUnder::Parent::Namespace,所以它不完全完美。

6

使用MooseClass::MOP基础,您可以找到分配给每个类(在该时间点)的子类。

Class::MOP::Class文档:

$ metaclass->子类 这将返回所有子类这个类,甚至间接子类的列表。

$ metaclass-> direct_subclasses 这将返回此类的直接子类的列表,该子类不包括间接子类。

因此,举例来说,如果我们建立这些类:

{ 
    package Root; 
    use Moose; 
    use namespace::clean -except => 'meta'; 

    sub baz  { say 'Some root thingy' } 
    sub download { say "downloading from " . __PACKAGE__ } 
} 

{ 
    package NodeA; 
    use Moose; 
    extends 'Root'; 
    use namespace::clean -except => 'meta'; 
    sub download { say "downloading from " . __PACKAGE__ } 
} 

{ 
    package NodeA1; 
    use Moose; 
    extends 'NodeA'; 
    use namespace::clean -except => 'meta'; 
    sub download { say "downloading from " . __PACKAGE__ } 
} 

然后使用你的例子,我们可以做到这一点的基础:

for my $pname (Root->new->meta->direct_subclasses) { 
    my $package = $pname->new; 
    $package->download; 
} 

# => "downloading from NodeA" 

所以上面运行NodeA->download。更改为meta->subclasses也将运行NodeA1->download

/I3az/

3

虽然你说你正在向Moose,非Moose的办法是把所有的衍生产品基于该基础包名已知的子目录。然后加载所有模块

例如,如果您的基本软件包是Local::Downloader,则所有派生软件包均以Local::Downloader::Plugin或类似内容开头。然后,您在@INC中查找所有模块.../Local/Downloader/Plugin/...。尽管自己做起来并不难,但像Module::PluginFinder这样的东西也可以为你做到。