使Moose构造函数忽略undef参数

Lum*_*umi 4 perl moose

哈希表是Perl对象的典型初始值设定项.现在你的输入是不可靠的,因为你不知道对于任何给定的键是否有定义的值,也不知道键是否存在.现在你想要将这些不可靠的输入提供给Moose对象,虽然缺少键是完全没问题的,但你确实希望摆脱未定义的值,这样你就不会得到一个充满未定义属性的对象.

在实例化对象并过滤掉未定义的值时,您当然可以非常小心.但是,假设你想在构造函数中安装该过滤器,因为它在一个地方.您希望构造函数忽略未定义的值,但不要在遇到它们时死掉.

对于访问器方法,您可以使用aroundaround来防止将属性设置为undef.但是这些方法修饰符不是为构造函数调用的,仅用于访问器.在Moose中是否有类似的设施来实现对c'tor的相同效果,即阻止任何undef属性被接受?

请注意,Any如果属性为undef ,则Moose 类型将在对象中创建哈希键.我不希望这样,因为我不想%$self包含任何undef值.

这是我做的一些测试:

package Gurke;
use Moose;
use Data::Dumper;

has color  => is => 'rw', isa => 'Str', default => 'green';
has length => is => 'rw', isa => 'Num';
has appeal => is => 'rw', isa => 'Any';

around color => sub {
    # print STDERR Dumper \@_;
    my $orig = shift;
    my $self = shift;
    return $self->$orig unless @_;
    return unless defined $_[0];
    return $self->$orig( @_ );
};

package main;
use Test::More;
use Test::Exception;

my $gu = Gurke->new;
isa_ok $gu, 'Gurke';
diag explain $gu;
ok ! exists $gu->{length}, 'attribute not passed, so not set';
diag q(attempt to set color to undef - we don't want it to succeed);
ok ! defined $gu->color( undef ), 'returns undef';
is $gu->color, 'green', 'value unchanged';
diag q(passing undef in the constructor will make it die);
dies_ok { Gurke->new( color => undef ) }
    'around does not work for the constructor!';
lives_ok { $gu = Gurke->new( appeal => undef ) } 'anything goes';
diag explain $gu;
diag q(... but creates the undef hash key, which is not what I want);
done_testing;
Run Code Online (Sandbox Code Playgroud)

Eth*_*her 13

这正是MooseX :: UndefTolerant所做的.如果你使你的类不可变,那么它将比编写你自己的BUILDARGS方法快得多,因为代码被内联到生成的构造函数中.

  • @Michael::)如果irc是你的事,你可以在irc.perl.org #moose找到一个24/7的优秀支持网络.通常情况下,如果没有一个扩展能够达到你想要的效果,那么有人会为你扯下并为你写一个,只是为了踢!:d (3认同)
  • @Michael在我使用Windows时我使用了XChat的Win32端口.我现在通过远程盒子上的ssh +屏幕会话使用irssi. (2认同)

Bra*_*ert 5

只需提供自己的BUILDARGS子程序.

package Gurke;

...

around 'BUILDARGS' => sub{
  my($orig,$self,@params) = @_;
  my $params;
  if( @params == 1 ){
    ($params) = @params;
  }else{
    $params = { @params };
  }

  for my $key ( keys %$params ){
    delete $params->{$key} unless defined $params->{$key};
  }

  $self->$orig($params);
};
Run Code Online (Sandbox Code Playgroud)