Как я могу найти все пакеты, которые наследуются от пакета в Perl? - PullRequest
4 голосов
/ 08 января 2010

У меня есть несколько различных сайтов, с которых я загружаю данные и делаю массаж в другие форматы (используя 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;
}

Это возможно или что-то подобное, возможно?

1011 * ТИА *

Ответы [ 4 ]

6 голосов
/ 08 января 2010

Используя Moose * Class::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 голосов
/ 08 января 2010

Хотя вы говорите, что переходите на Moose, не Moose способ - это поместить все производные пакеты в известный подкаталог на основе имени базового пакета. Затем вы загружаете все модули

Например, если ваш базовый пакет Local::Downloader, все производные пакеты начинаются с Local::Downloader::Plugin или чего-то подобного. Затем вы ищете все модули в вашем @INC столько, сколько .../Local/Downloader/Plugin/.... Хотя это не так сложно сделать самому, что-то вроде Module :: PluginFinder может сделать это и для вас.

2 голосов
/ 08 января 2010

То, о чем вы просите, будет невозможно, потому что ни один из пакетов, которые вы хотите использовать, не будет загружен. Почему бы не поместить все пакеты в общий каталог, а затем сделать так, чтобы ваш сценарий открыл этот каталог, и для каждого файла потребовал его, а затем создать экземпляр ваших объектов.

1 голос
/ 08 января 2010

Нет способа сделать это на основе наследования, потому что родительский класс даже не знает, есть ли у него потомки, не говоря уже о том, сколько у него есть или как их зовут.

Однако, если вы следуете общепринятому соглашению об использовании иерархических пространств имен и именуете потомков как Parent::Foo, Parent::Bar и т. Д., Вы можете приблизить это, используя Module :: Pluggable для загрузки все под Parent пространством имен:

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

Так как это основано на пространствах имен, оно будет вытягивать Parent::Helper::ThatIsNotAChild, в то время как отсутствует Child::NotUnder::Parent::Namespace, поэтому оно не совсем идеально.

...