Я уверен, что это где-то описано в документации, но мне не удалось его найти ... Я ищу синтаксический сахар, который позволит вызвать метод в классе, имя которого хранится в хэше ( в отличие от простого скаляра):
use strict; use warnings;
package Foo;
sub foo { print "in foo()\n" }
package main;
my %hash = (func => 'foo');
Foo->$hash{func};
Если я сначала скопирую $hash{func}
в скалярную переменную, тогда я могу нормально вызвать Foo->$func
... но чего не хватает для работы Foo->$hash{func}
?
(РЕДАКТИРОВАТЬ: я не собираюсь делать что-то особенное, вызывая метод класса Foo
- это может так же легко быть благословенным объектом (и в моем реальном коде это так); просто было проще написать само- содержит пример с использованием метода класса.)
РЕДАКТИРОВАТЬ 2: Просто для полноты комментариев ниже, это то, что я на самом деле делаю (это в библиотеке сахара атрибутов Moose, созданной с помощью Moose :: Exporter):
# adds an accessor to a sibling module
sub foreignTable
{
my ($meta, $table, %args) = @_;
my $class = 'MyApp::Dir1::Dir2::' . $table;
my $dbAccessor = lcfirst $table;
eval "require $class" or do { die "Can't load $class: $@" };
$meta->add_attribute(
$table,
is => 'ro',
isa => $class,
init_arg => undef, # don't allow in constructor
lazy => 1,
predicate => 'has_' . $table,
default => sub {
my $this = shift;
$this->debug("in builder for $class");
### here's the line that uses a hash value as the method name
my @args = ($args{primaryKey} => $this->${\$args{primaryKey}});
push @args, ( _dbObject => $this->_dbObject->$dbAccessor )
if $args{fkRelationshipExists};
$this->debug("passing these values to $class -> new: @args");
$class->new(@args);
},
);
}
Я заменил отмеченную строку выше на это:
my $pk_accessor = $this->meta->find_attribute_by_name($args{primaryKey})->get_read_method_ref;
my @args = ($args{primaryKey} => $this->$pk_accessor);
PS. Я только что заметил, что этот же метод (использование мета-класса Moose для поиска ссылки на код вместо принятия его соглашения об именах) нельзя также использовать для предикатов, так как Class :: MOP :: Attribute не имеет аналогичного get_predicate_method_ref
метода доступа. :(
my $reader_ref = $this->meta->find_attribute_by_name($fieldname)->get_read_method_ref;
(см. Class :: MOP :: Class и Class :: MOP :: Attribute), но все это позволяет избежать того, что читателю присвоено имя, отличное от имени атрибута. - person Ether   schedule 03.12.2009$this->$reader_ref()
, и он будет намного чище, чем версия по имени. У PBP есть хорошее объяснение, почему использование подссылки - лучший способ сделать это, если кому-то интересно. - person Robert P   schedule 03.12.2009$attr->set_value($instance, $value)
, чем делать предположения о том, что вызывается аксессор. - person Ether   schedule 08.06.2010