考虑以下示例:
use 5.010;
use Data::Dumper;
{
package MyTestPck;
use Data::Dumper;
use Tie::IxHash;
sub ordered_hash { # http://stackoverflow.com/a/3001400/277826
tie my %hash => 'Tie::IxHash';
%hash = @_;
\%hash
}
my $fields = ordered_hash(
(map { $_ => $_ } (qw(
varA
varB
varC
)))
);
print Dumper($fields);
use Class::XSAccessor
accessors => {
%{$fields}
};
sub new {
my $class = shift;
my @set_arr = @_; # the rest
my $ic = 0; my $self = {};
bless $self, $class;
for my $k (keys %{$fields}) {
my $fld = $fields->{$k};
my $val = $set_arr[$ic];
print("k $k fld $fld ic/val $ic $val\n");
$self->$fld($val);
$ic++;
}
return $self;
}
1;
}
my $pcktestobj = MyTestPck->new((10, 20, 30));
print Dumper($pcktestobj);
如果我按原样运行;代码失败了:
$ perl /tmp/test.pl
$VAR1 = {
'varA' => 'varA',
'varB' => 'varB',
'varC' => 'varC'
};
k varA fld varA ic/val 0 10
Can't locate object method "varA" via package "MyTestPck" at /tmp/test.pl line 34.
但是,如果用以下代码替换代码的中间部分:
...
use Class::XSAccessor
accessors => ordered_hash(
(map { $_ => $_ } (qw(
varA
varB
varC
)))
);
...
...然后输出符合预期:
$ perl /tmp/test.pl
$VAR1 = {
'varA' => 'varA',
'varB' => 'varB',
'varC' => 'varC'
};
k varA fld varA ic/val 0 10
k varB fld varB ic/val 1 20
k varC fld varC ic/val 2 30
$VAR1 = bless( {
'varC' => 30,
'varB' => 20,
'varA' => 10
}, 'MyTestPck' );
所以,显然,我不能通过预定义的哈希设置访问器,如use Class::XSAccessor accessors => { %{$fields} };
- 我显然必须指定内联的访问器哈希。
但为什么会这样呢? Class::XSAccessor docs中是否有任何内容可以提醒我这种行为?有没有办法可以使用预定义字段(我在第一个示例中的意图)使用Class::XSAccessor
?
答案 0 :(得分:1)
use
语句在编译时执行,但您的哈希不会在运行时之前填充。看看这个例子:
my $x = {}; # this statement is executed **SECOND**
use strict; # this statement is executed **FIRST**
因此,您无法在上面$x
语句中使用use
变量。 <{1}}尚未定义。
幸运的是,$x
语句可以轻松分解为use
后跟require
。每个都发生在运行时。所以尝试替换它:
import
有了这个:
use Class::XSAccessor
accessors => {
%{$fields}
};
另一种方法是强制require Class::XSAccessor;
Class::XSAccessor->import( accessors => $fields );
在编译时填充。这应该有效,但不太漂亮:
$fields