Perl ссылается на метод класса - PullRequest
1 голос
/ 04 марта 2010

Допустим, у меня есть Perl-модуль Resounces.pm с этим фрагментом кода

my $my_class = new MY_CLASS;
our resource => { '/list' => $my_class->list_files() };

Так можно ли назвать эту переменную ресурса в другом Perl-скрипте чем-то вроде этого?

use Resources;
$Resources::resource->{'/list'};

Мое намерение состоит в том, чтобы выполнить метод list_files (), когда я использую этот последний оператор. Это вообще возможно?

1 Ответ

4 голосов
/ 04 марта 2010

Один из вариантов - использовать анонимную подпрограмму:

package Resources;
my $my_class = new MY_CLASS;
our $resource = { '/list' => sub { $my_class->list_files(@_); } };

...

package main;
# dereference the code ref
&{$Resources::resource->{'/list'}};
# or call it:
$Resources::resource->{'/list'}();

Если вы измените ссылки $my_class, они также будут изменены в анонимной функции. Это может быть то, что вы хотите; если нет, продолжайте чтение для функции (bindMethod), которая связывает объект и метод.

Если вы не хотите, чтобы анонимная функция появлялась в стеке:

our $resource = { '/list' => sub { unshift @_, $my_class; 
                                   goto &MyClass::list_files; } };

Обратите внимание, что эта форма goto не является обычной инструкцией goto - это хвостовой вызов .

Вы могли бы определить вспомогательный метод для настройки привязки, хотя, честно говоря, он мало что дает.

sub bindMethod {
    my ($obj, $meth) = @_;
    return sub { unshift @_, $obj; goto &{$meth}; }
}

my $my_class = new MyClass;
our $resource = { '/list' => bindMethod($my_class, \&MyClass::list_files) };

Вот версия bindMethod, которая не требует указания класса с именем метода.

sub bindMethod {
    my ($obj, $meth) = @_;
    if (! ref $meth) {
        my $class = ref $obj;
        $meth = \&{"${class}::$meth"};
    }
    return sub { unshift @_, $obj; goto &{$meth}; }
}
...
my $my_class = new MyClass;
our $resource = { '/list' => bindMethod($my_class, 'list_files') };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...