为什么声明一个在Moose中返回子程序引用的子程序?

时间:2013-07-16 02:49:03

标签: perl moose

我是perl的Moose新手,当我遇到这个我不太明白的文章时,我一直在阅读它的文档:

如果要使用任何类型的引用作为默认值,则必须从子例程返回它。 好的我得到这个陈述,下一个例子

has 'mapping' => (
      is      => 'ro',
      default => sub { {} },
  );

这是必要的,因为否则Perl只会实例化一次引用,并且它将由所有对象共享:这个我不明白,它是什么意思,它将实例化一次引用并将被共享所有对象?怎么样?

 has 'mapping' => (
      is      => 'ro',
      default => {}, # wrong!
  );

如果您将裸的非子例程引用作为默认值传递,则Moose将抛出错误。

如果Moose允许这样做,那么默认的映射属性很容易在许多对象之间共享。相反,如上所述,将其包装在子例程引用中。 不要再这样了

1 个答案:

答案 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