由于不完整的数据被提供给我的Moose构造函数,我从QA收到了很多异常。属性名称存在于构造函数参数中,但值为undef
。
许多脚本应用程序都是事实,事情只是undef
。而且这通常很好。你不希望来自warnings
pragma的恼人警告(所以你做no warnings 'uninitialized'
),你肯定不希望你的代码死掉,因为一个小的值,比如housenumber,是{{ 1}}。
所以不用多说,我希望我的Moose构造函数表现得像直接Perl(即没有undef
),即将use warnings 'uninitialized'
转换为undef
或根据需要转换为空字符串。此示例中显示的尝试不适用于存在属性名称但值为0
的情况。我可以考虑使用undef
来实现我想要的。但是在没有resorting to MooseX::UndefTolerant的普通Moose中是否有一种声明性的方式(遗憾的是我不能使用它,因为它没有安装)?
BUILDARGS
答案 0 :(得分:9)
在Moose::Manual::Types中,记录的方式可以解决这类问题。
使用Maybe[a]
类型。
package AAA;
use Moose;
has 'hu', is => 'ro', isa => 'Str';
has 'ba', is => 'ro', isa => 'Int';
no Moose; __PACKAGE__->meta->make_immutable;
package BBB;
use Moose; extends 'AAA';
has 'hu', is => 'rw', isa => 'Maybe[Str]', default => ''; # will not die on undef
has 'ba', is => 'rw', isa => 'Maybe[Int]', default => 0; # idem
sub BUILD {
my $self = shift;
$self->hu('') unless defined $self->hu;
$self->ba(0) unless defined $self->ba;
}
no Moose; __PACKAGE__->meta->make_immutable;
package main;
use Test::More;
use Test::Exception;
# Those AAAs should die ...
throws_ok { AAA->new( hu => undef ) }
qr/Validation failed for 'Str' with value undef/;
throws_ok { AAA->new( ba => undef ) }
qr/Validation failed for 'Int' with value undef/;
# .. but these BBBs should live:
lives_ok { BBB->new( hu => undef ) } 'hu supplied as undef';
lives_ok { BBB->new( ba => undef ) } 'ba supplied as undef';
my $bbb = BBB->new( hu => undef, ba => undef );
is $bbb->hu, '', "hu is ''";
is $bbb->ba, 0, 'ba is 0';
done_testing;
答案 1 :(得分:4)
你的抱怨确实是穆斯正在做的事情正是应该做的。如果您明确地将undef
作为值传递,但该值只能是Int
,那么您应该收到错误。
所以你需要做出选择。您可以更改类型(通过union)以允许undef
作为有效值,如下所示:
has 'hu', is => 'ro', isa => 'Str | Undef';
has 'ba', is => 'ro', isa => 'Int | Undef';
或者您可以不发送未定义的值:
my %aa_params = ();
$aa_params{hu} = $foo if defined $foo;
$aa = AA->new( %aa_params );
或者最后,由于一些未知的原因,你绝对无法拒绝为不应该明确设置为undefined的事物发送无效的未定义值,只需写一个快速过滤器:
sub filt_undef {
my %hash = @_;
return map { $_ => $hash{$_} } grep { defined $hash{$_} } keys %hash;
}
$aa = AA->new( filt_undef( hu => undef ) );
但这看起来很尴尬和可怕。
答案 2 :(得分:2)
或使用即时强制:
package BBB;
use Moose;
use MooseX::AttributeShortcuts;
extends 'AAA';
has '+hu',
traits => [Shortcuts],
coerce => [ Undef => sub { '' } ],
;