How can I require a Moose constructor arg that is not a attribute?
I have a Moose object module that should accept a relatively large data structur开发者_如何学Pythone (ds
) as one of its constructor arguments. It is used to calculate some of the object's attributes. However, I do not wish to store ds
itself as an attributes -- it is only needed during the construction of the object.
I thought of using BUILDARGS
but then I'm not sure how to define that ds
is a required argument.
How can I work around this?
I'd be inclined to have a constructor that takes only the calculated values derived from your data structure. Then use a different method to take limited params plus the data structure as args.
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;
}
Then make your objects like so:
my $foo = Foo->generate_foo_from_ds( foo_data => $bar, foo => 1, bar => 2, baz => 2 );
Now you don't have to worry about weird serialization issues or BUILDARGS or even BUILD. You have a simple method and that is all.
You could use either BUILD
or BUILDARGS
for this. It's hard to say which would be better without knowing more about what you're trying to do, but I'd guess BUILD
would be the better choice.
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
If you want Moose to check the type and ensure it's present, you have to make it an attribute. But you can clear it in the BUILD
method after you use it.
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
You could name the reader method something else (like _ds
) if you wanted to.
精彩评论