Как объект получает доступ к таблице символов для текущего пакета?

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 сообщает вам пакет, из которого он был вызван. (Здесь я добавил несколько стандартных 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 не выполняет Устранение общего выражения Sube, поэтому вы можете также 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