如果给出下面的代码,您安装对象的顺序似乎很重要。下面的代码将为两个对象打印相同的列表,而我希望每个对象都有一个不同的列表,因为list是在构建时创建的实例属性。
package t;
use Moo;
use Types::Standard qw(ArrayRef);
my @list = qw/foo bar baz/;
has list => (
is => 'rw',
isa => ArrayRef,
default => sub {\@list}
);
1;
---
package u;
use Moo;
use Types::Standard qw(ArrayRef);
extends 't';
sub BUILD {
my ($self) = @_;
push @{$self->list()}, qw/apple banana/;
return $self;
}
1;
---
#!perl
use Data::Printer;
use t;
use u;
my $u = u->new();
p $u->list();
my $t = t->new();
p $t->list();当前产出:
\ [
[0] "foo",
[1] "bar",
[2] "baz",
[3] "apple",
[4] "banana"
]
\ [
[0] "foo",
[1] "bar",
[2] "baz",
[3] "apple",
[4] "banana"
]预期产出:
\ [
[0] "foo",
[1] "bar",
[2] "baz",
[3] "apple",
[4] "banana"
]
\ [
[0] "foo",
[1] "bar",
[2] "baz"
]发布于 2019-03-07 15:38:10
由于您更改了所讨论的数组,所以不希望引用用作默认\@list的数组,因此您希望获得一个浅拷贝[@list]。
package t;
use Moo;
use Types::Standard qw(ArrayRef);
my @list = qw/foo bar baz/;
has list => (
is => 'rw',
isa => ArrayRef,
builder =>
default => sub { [@list] }
);
package u;
use Moo;
use Types::Standard qw(ArrayRef);
extends 't';
sub BUILD {
my ($self) = @_;
push @{$self->list()}, qw/apple banana/;
return $self;
}
package main;
use Data::Printer;
my $u = u->new();
p $u->list();
my $t = t->new();
p $t->list();当我这样做的时候,使用BUILD来修改属性是可能的,但不一定是最好的。您可以在构建器方法中使用一些类似于延迟属性的内容,然后在子类ala中重载该方法。
package t;
use Moo;
use Types::Standard qw(ArrayRef);
my @list = qw/foo bar baz/;
has list => (
is => 'rw',
isa => ArrayRef,
builder => '_build_list',
lazy => 1,
);
sub _build_list {
my $self = shift;
return [@list];
}
package u;
use Moo;
extends 't';
sub _build_list {
my $self = shift;
my $list = $self->SUPER::_build_list();
push @$list, qw/apple banana/;
return $list;
}
package main;
use Data::Printer;
my $u = u->new();
p $u->list();
my $t = t->new();
p $t->list();https://stackoverflow.com/questions/55047234
复制相似问题