我是perl的Moose新手,当我遇到这个我不太明白的文章时,我一直在阅读它的文档:
如果要使用任何类型的引用作为默认值,则必须从子例程返回它。 好的我得到这个陈述,下一个例子
has 'mapping' => (
is => 'ro',
default => sub { {} },
);
这是必要的,因为否则Perl只会实例化一次引用,并且它将由所有对象共享:这个我不明白,它是什么意思,它将实例化一次引用并将被共享所有对象?怎么样?
has 'mapping' => (
is => 'ro',
default => {}, # wrong!
);
如果您将裸的非子例程引用作为默认值传递,则Moose将抛出错误。
如果Moose允许这样做,那么默认的映射属性很容易在许多对象之间共享。相反,如上所述,将其包装在子例程引用中。 不要再这样了
答案 0 :(得分:2)
因为它会在远处创建动作,这很糟糕。问题的插图:
package Wrong;
my $default = {};
sub new {
my ($class) = @_;
return bless $default => $class;
}
package main;
use 5.010;
my @wobj;
push @wobj, Wrong->new for 0..2;
$wobj[0]->{some_new_attr} = 'foobar';
use Data::Dumper qw(Dumper);
print Dumper $wobj[1]; # huh????!
print Dumper $wobj[2]; # that one, too?! why?
say for @wobj; # ah, it's the same shared address
package Correct;
my $default = sub { return {} };
sub new {
my ($class) = @_;
return bless $default->() => $class;
}
package main;
my @cobj;
push @cobj, Correct->new for 0..2;
$cobj[0]->{some_new_attr} = 'foobar';
print Dumper $cobj[$_] for 0..2; # instances 1 and 2 are unaffected
say for @cobj; # all different addresses