Хеш-таблица является типичным инициализатором для ваших объектов Perl. Теперь ваш ввод ненадежен в том смысле, что вы не знаете, будет ли для какого-либо данного ключа определенное значение, и есть ли вообще ключ. Теперь вы хотите передать такой ненадежный ввод в объекты Moose, и, хотя отсутствующие ключи в порядке, вы хотите избавиться от неопределенных значений, чтобы не получить объект, полный неопределенных атрибутов.
Вы, безусловно, можете быть очень осторожны при создании экземпляров объектов и отфильтровывать неопределенные значения. Но допустим, вы хотите установить этот фильтр в своем конструкторе, потому что тогда он находится в одном месте. Вы хотите, чтобы конструктор игнорировал неопределенные значения, но не умирал при их обнаружении.
Для методов доступа вы можете использовать around
, чтобы атрибут не был установлен на undef
. Но эти модификаторы метода не вызываются для конструктора, только для методов доступа. Есть ли в Moose аналогичное средство для достижения того же эффекта для c'tor, то есть для предотвращения принятия любых атрибутов undef
?
Обратите внимание, что тип Moose Any
создает хеш-ключ в объекте, если атрибут undef. Я не хочу этого, потому что я хочу, чтобы %$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;