我有一个Moose对象模块,它应该接受一个相对较大的数据结构(ds
)作为其构造函数参数之一。它用于计算对象的一些属性。但是,我不希望将ds
本身存储为属性 - 只有在构造对象时才需要它。
我想过使用BUILDARGS
,但后来我不确定如何定义ds
是必需的参数。
我该如何解决这个问题?
答案 0 :(得分:3)
我倾向于拥有一个只接受从数据结构派生的计算值的构造函数。然后使用不同的方法将有限的参数加上数据结构作为参数。
sub generate_foo_from_ds {
my $class = shift;
my %arg = @_;
my $ds = $arg{foo_data};
# Get attributes from args
my %attrib;
for (qw(foo bar baz ) {
croak "Attrib '$_' is required" unless exists $arg{$_};
$attrib{$_} = $arg{$_};
}
# calculate some more attributes here.
$attrib{griz} = $ds->{whee} * $ds->{whoosh} / $ds->{whiz}[12];
my $foo = $class->new( %attrib );
return $foo;
}
然后像这样制作你的物品:
my $foo = Foo->generate_foo_from_ds( foo_data => $bar, foo => 1, bar => 2, baz => 2 );
现在您不必担心奇怪的序列化问题或BUILDARGS甚至BUILD。你有一个简单的方法,就是这样。
答案 1 :(得分:2)
您可以使用BUILD
或BUILDARGS
。很难说如果不了解更多关于你要做的事情哪个更好,但我猜BUILD
将是更好的选择。
sub BUILD {
my $self = shift;
my $args = shift;
my $ds = $args->{ds} or confess "Argument (ds) is required";
$self->some_attr($ds->{...});
$self->other_attr($ds->{foo}[3]);
...
} # end BUILD
如果您希望Moose检查类型并确保其存在,则必须将其设为属性。但是您可以在使用它之后在BUILD
方法中清除它。
has 'ds' => (
is => 'ro',
isa => 'SomeType',
required => 1,
clearer => '_clear_ds',
);
sub BUILD {
my $self = shift;
my $args = shift;
my $ds = $self->ds;
$self->_clear_ds;
$self->some_attr($ds->{...});
$self->other_attr($ds->{foo}[3]);
...
} # end BUILD
如果您愿意,可以将读者方法命名为其他内容(如_ds
)。