我怎么能要求一个不属于属性的Moose构造函数arg?

时间:2010-10-26 07:27:09

标签: perl constructor moose

我有一个Moose对象模块,它应该接受一个相对较大的数据结构(ds)作为其构造函数参数之一。它用于计算对象的一些属性。但是,我不希望将ds本身存储为属性 - 只有在构造对象时才需要它。

我想过使用BUILDARGS,但后来我不确定如何定义ds是必需的参数。

我该如何解决这个问题?

2 个答案:

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

您可以使用BUILDBUILDARGS。很难说如果不了解更多关于你要做的事情哪个更好,但我猜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)。