4

仕事で使用するために、データをダウンロードして (Perl を使用して) 他の形式に変換するさまざまなサイトがいくつかあります。これらはすべて、次のような 1 つの 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;
}

それは可能ですか?

ティア

4

4 に答える 4

6

Mooseの基盤を使用Class::MOPして、各クラスに割り当てられたサブクラスを見つけることができます(その時点で)。

Class::MOP::Classドキュメントから:

$ metaclass-> subclasses これは、間接サブクラスも含め、このクラスのすべてのサブクラスのリストを返します。

$ 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 /

于 2010-01-08T10:25:56.360 に答える
3

に移動すると言いましたがMooseMooseすべての派生パッケージを基本パッケージ名に基づいて既知のサブディレクトリに配置することはできません。次に、すべてのモジュールをロードします

たとえば、ベース パッケージが の場合Local::Downloader、すべての派生パッケージは で始まりますLocal::Downloader::Plugin。次に、それだけですべてのモジュールを探し@INCます.../Local/Downloader/Plugin/...。自分で行うのはそれほど難しいことではありませんが、Module::PluginFinderのようなものを使用して行うこともできます。

于 2010-01-08T11:09:31.017 に答える
2

使用しようとしているパッケージがまだロードされていないため、あなたが求めていることは不可能です。すべてのパッケージを共通のディレクトリに配置し、スクリプトでそのディレクトリを開き、ファイルごとにそれを要求してから、オブジェクトをインスタンス化しないでください。

于 2010-01-08T03:39:53.233 に答える
1

親クラスは子孫があるかどうかさえ知らないため、継承に基づいてこれを行う方法はありません。子孫がいくつあるか、名前が何であるかは気にしないでください。

ただし、階層名前空間を使用し、子孫Parent::Fooに、などの名前を付けるという一般的な規則に従う場合は、 Module::Pluggableを使用して名前空間の下にすべてをロードすることでParent::Barこれを概算できます。Parent

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

ただし、これは名前空間に基づいているためParent::Helper::ThatIsNotAChild、が欠落している間は引き込まれ、Child::NotUnder::Parent::Namespace完全ではありません。

于 2010-01-08T10:19:16.313 に答える