现在有:

has 'id' => (
    is => 'rw',
    isa => 'Str',
    default => sub { "id" . int(rand(1000))+1 }
);


可以,可以:

PKG->new(id => 'some'); #the id is "some"
PKG->new()              #the id is #id<random_number>


在下一个场景中:

my $value = undef;
PKG->new(id => $value);


(当然)出现错误:

Attribute (id) does not pass the type constraint because: Validation failed for 'Str' with value undef at /Users/me/perl5/perlbrew/perls/perl-5.16.3/lib/site_perl/5.16.3/darwin-thread-multi-2level/Moose/Exception.pm line 37


问题是:

将值设置为undef后(仅当它为$ undef时)如何实现更改?所以,

has 'id' => (
    is => 'rw',
    isa => 'Str|Undef',  #added undef to acceptable Type
    default => sub { "id" . int(rand(1000))+1 }
);


现在,它接受$undef,但是我不想要$undef,但想要"id" . int(rand(1000))+1。设置后如何更改属性值?

after仅针对访问器而不是构造函数被调用。从coercionUndef也许有些怪异的Str-但仅针对这一属性?

附言:使用PKG->new( id => $value // int(rand(10000)) )是不可接受的解决方案。模块应接受$undef,并应将其静默更改为随机数。

最佳答案

Type::Tiny的目标之一就是使其真正容易地轻松地向各个属性添加强制。这是一个例子:

use strict;
use warnings;

{
    package Local::Test;
    use Moose;
    use Types::Standard qw( Str Undef );

    my $_id_default = sub { "id" . int(rand(1000)+1) };

    has id => (
        is      => 'rw',
        isa     => Str->plus_coercions(Undef, $_id_default),
        default => $_id_default,
        coerce  => 1,
    );

    __PACKAGE__->meta->make_immutable;
}

print Local::Test->new(id => 'xyz123')->dump;
print Local::Test->new(id => undef)->dump;
print Local::Test->new->dump;


您还可以查看MooseX::UndefTolerant,它使传递到构造函数的undef值就像完全被忽略一样。但是,这将不包括将undef传递给访问者。只是构造函数。

09-30 17:35
查看更多