由于不完整的数据被提供给我的Moose构造函数,我收到了很多QA例外.属性名称存在于构造函数参数中,但值为undef.
对于许多脚本应用程序来说,这是事实上的事实.而且这通常很好.你不希望来自警告pragma的恼人的警告(所以你没有警告’未初始化’),你当然不希望你的代码死亡,因为一个小的值,比如housenumber,是undef.
所以不用多说,我希望我的Moose构造函数表现得像直接Perl(即没有使用警告’未初始化’),即将undef转换为0或根据需要将空字符串转换为空字符串.此示例中显示的尝试不适用于存在属性名称但值为undef的情况.我可以想到使用BUILDARGS实现我想要的.但是在没有resorting to MooseX::UndefTolerant的普通Moose中是否有一种声明性的方式(遗憾的是我不能使用,因为它没有安装)?
package AAA; use Moose; has 'hu',is => 'ro',isa => 'Str'; has 'ba',isa => 'Int'; no Moose; __PACKAGE__->Meta->make_immutable; package BBB; use Moose; extends 'AAA'; has '+hu',default => ''; # don't want to die on undef has '+ba',default => 0; # idem 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'; done_testing;
解决方法
在
Moose::Manual::Types中有一种记录方式来处理这种问题.
使用Maybe [a]类型.
package AAA; use Moose; has 'hu',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',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,'ba is 0'; done_testing;