객체가 현재 패키지의 기호 테이블에 어떻게 액세스합니까?

StackOverflow https://stackoverflow.com/questions/1822312

  •  10-07-2019
  •  | 
  •  

문제

객체가 인스턴스화된 현재 패키지의 기호 테이블에 어떻게 액세스할 수 있습니까?예를 들어 다음과 같은 것이 있습니다.

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 은 현재 패키지이며 기호 테이블을 검색합니다.나는 사용해 보았다. Scalar::Util축복받았어, 그래도 나한테는 도움이 됐어 MyModule 대신에 main.이제 좀 더 명확해졌기를 바랍니다.

도움이 되었습니까?

해결책

당신은 단지 원한다 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'.

다른 팁

보다 perldoc -f 호출자:

#!/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
No, you can't!
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top