"Соединение" объекта Moo с хэшем
В моем реальном коде я хочу "синхронизировать" объект Moo (или Moose, если Moo не будет работать) с хэшем (в действительности связанным хэшем), так что чтение свойства объекта Moo считало бы соответствующее значение из хэша и запись свойства объекта Moo сохраняла бы в хэше.
Следующий упрощенный код:
#!/usr/bin/perl
use feature qw(say);
package X;
use Moo;
use Data::Dumper;
my $BusinessClass = 'X';
has 'base' => (is => 'rw', builder => 'base_builder');
sub base_builder {
return {};
}
foreach my $Key (qw(a b c)) {
{
no strict 'refs';
*{"${BusinessClass}::$Key"} = sub {
if (@_ == 2) {
return $_[0]->base->{$Key} = $_[1];
} else {
return $_[0]->base->{$Key};
}
};
has $Key => ( is => 'rw',
lazy => 0,
required => 0,
reader => "${BusinessClass}::_access1_$Key",
writer => "${BusinessClass}::_access2_$Key",
);
}
}
my $obj = X->new(a=>123, b=>456);
print Dumper $obj->base;
$obj->c(789);
print Dumper $obj->base;
Проблема в том, что атрибуты, передаваемые функции new
, не хранятся в has $obj->base
(но они должны быть). В приведенном выше примере кода атрибут c
хранится должным образом, но a
и b
не хранятся в хэше. Это ошибка.
Каковы хорошие способы справиться с этой ситуацией?
1 ответ:
Это можно решить, добавив:
sub BUILD { my ($self, $args) = @_; foreach my $Key (keys %$args) { $self->base->{$Key} = $args->{$Key}; my $clearer = "_clear_local_$Key"; $self->$clearer(); } }
Полный код:
#!/usr/bin/perl use feature qw(say); package X; use Moo; use Data::Dumper; my $BusinessClass = 'X'; has 'base' => (is => 'rw', builder => 'base_builder'); sub base_builder { return {}; } sub BUILD { my ($self, $args) = @_; foreach my $Key (keys %$args) { $self->base->{$Key} = $args->{$Key}; my $clearer = "_clear_local_$Key"; $self->$clearer(); } } foreach my $Key (qw(a b c)) { { no strict 'refs'; *{"${BusinessClass}::$Key"} = sub { if (@_ == 2) { return $_[0]->base->{$Key} = $_[1]; } else { return $_[0]->base->{$Key}; } }; has $Key => ( is => 'rw', lazy => 0, required => 0, reader => "${BusinessClass}::_access1_$Key", writer => "${BusinessClass}::_access2_$Key", clearer => "_clear_local_$Key", ); } } my $obj = X->new(a=>123, b=>456); print Dumper $obj->base; $obj->c(789); print Dumper $obj->base; print Dumper {%$obj};