1

オブジェクトがインスタンス化された現在のパッケージのシンボルテーブルにアクセスするにはどうすればよいですか?たとえば、私は次のようなものを持っています:

my $object = MyModule->new;
# this looks in the current package, to see if there's a function named run_me
# I'd like to know how to do this without passing a sub reference
$object->do_your_job;

do_your_job私が使用する実装では、パッケージ__PACKAGE__内を検索します。MyModuleどうすれば適切なパッケージで表示できますか?

編集:私はこれをより明確にしようとします。次のコードがあるとします。

package MyMod;

sub new {
    return bless {},$_[0]
}

sub do_your_job {
    my $self = shift;
    # of course find_package_of is fictional here
    # just for this example's sake, $pkg should be main
    my $pkg = find_package_of($self);
    if(defined &{ $pkg . '::run_me' }) {
        # the function exists, call it.
    }
}

package main;

sub run_me {
   print "x should run me.\n";
}

my $x = MyMod->new;

# this should find the run_me sub in the current package and invoke it.
$x->do_your_job;

さて、$xどういうわけかそれが現在のパッケージであることに気づき、mainそれのシンボルテーブルを検索する必要があります。's blessedを使ってみScalar::Utilましたが、それでも。MyModuleの代わりに私に与えてくれましたmain。うまくいけば、これはもう少し明確になりました。

4

2 に答える 2

6

あなたはただ欲しいcaller

caller呼び出されたパッケージを示します。(ここにいくつかの標準的なperlを追加しました。)

use Symbol qw<qualify_to_ref>;
#...
my $pkg = caller;

my $symb   = qualify_to_ref( 'run_me', $pkg );
my $run_me = *{$symb}{CODE};
$run_me->() if defined $run_me;

それを調べて、それが定義されているかどうかを確認してから、それを呼び出すためにそれを呼び出すには、標準のperlは共通部分式除去を行わないため、それを複製します。したがって、1)それを取得し、2)スロットの定義を確認することもできます。 3)定義されている場合は実行します。

これで、あるパッケージでオブジェクトを作成し、それを別のパッケージで使用する場合、それはあまり役に立ちません。'owning_package'コンストラクターのように、おそらくフィールドを追加する必要があります。

package MyMod;

#...
sub new { 
    #...
    $self->{owning_package} = caller || 'main';
    #...
}

$x->{owning_package}これでが含まれます'main'

于 2009-11-30T21:33:50.740 に答える
1

perldoc-fcallerを参照してください。

#!/usr/bin/perl

package A;
use strict; use warnings;

sub do_your_job {
    my ($self) = @_;
    my ($pkg) = caller;
    if ( my $sub = $pkg->can('run_me') ) {
        $sub->();
    }
}

package B;
use strict; use warnings;

sub test {
    A->do_your_job;
}

sub run_me {
    print "No, you can't!\n";
}

package main;

use strict; use warnings;

B->test;

出力:

C:\ Temp> h
いいえ、できません!
于 2009-11-30T21:13:08.223 に答える