2009-11-30 2 views
0

개체가 인스턴스화 된 현재 패키지의 기호 테이블에 어떻게 액세스 할 수 있습니까? 개체가 현재 패키지의 기호 테이블에 어떻게 액세스합니까?

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; 

내가 __PACKAGE__를 사용 do_your_job의 구현의 경우

, 그것은 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의 축복을 사용하여 시도했지만, 여전히 main 대신 MyModule을주었습니다. 바라기를, 이것은 지금 조금 더 명확하다.

+1

이와 같은 문제가 발생하면 내가 뒤집은 첫 번째 장소 중 하나는 perlfunc의 카테고리 별 Perl 함수 섹션입니다. 이 문제와 관련이있을 수있는 것들을 쉽게 찾을 수 있도록 내장 된 목록을 멋지게 그룹화했습니다. 이 경우 '범위와 관련된 키워드'섹션에는 8 가지 항목이 있습니다. 첫 번째는'호출자 (caller) '입니다. http://perldoc.perl.org/perlfunc.html#Perl-Functions-by-Category – daotoad

+0

옳은 대답이 무엇인지 확립 했으니 까, 왜이 일을하고 싶은지 궁금합니다. 객체를 인스턴스화 한 패키지의 심볼 테이블에 액세스하는 메서드를 사용하면 대다수 상황에서 매우 나쁜 생각으로 인식됩니다. –

+0

이 튜토리얼은 Win32 :: GUI 용 http://search.cpan.org/~ROBERTMAY/Win32-GUI/docs/GUI/Tutorial/Part1.pod를 보았고, 이것이'Main_Terminate'가 어떻게 구현되었는지 상상했습니다. – Geo

답변

6

당신은 caller

caller 당신이 호출 된 패키지를 지시합니다. (여기 좀 표준 펄을 추가했습니다.)

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; 

를 찾으려면 당신이 수도 있으므로,이 공통 부분 식 제거하지 않는 표준 펄로 복제 할 전화를 찾아 다음이 정의되어 있는지 확인하고 1) 그것을 검색하고, 2) 슬롯의 정의를 확인하고, 3) 정의 된 경우 실행하십시오.

한 패키지에 하나의 객체를 만들고 다른 패키지에서 사용하면 너무 많은 도움이되지 않습니다. 생성자에 'owning_package'과 같은 추가 필드를 추가해야 할 수 있습니다.

package MyMod; 

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

지금 $x->{owning_package}'main' 포함됩니다.

+2

+1입니다. –

+1

재미있는 신난 :)! 이것이 내가 처음부터 원했던 것이 분명하다는 것입니다. – Geo

+1

@Geo 그럼 편집 이력을 사용할 수있는 좋은 방법입니다. 내 말은, 합리적이지 않은 3 명의 사람들이 당신이 묻는 것을 오해하고 명확히해야한다는 것입니다. –

1

perldoc -f caller를 참조하십시오

#!/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! 
관련 문제