Perl Moose с несколькими взаимозависимыми атрибутами - PullRequest
0 голосов
/ 01 мая 2018

Как я могу создать свой класс Perl Moose, чтобы несколько взаимозависимых атрибутов строились в правильном порядке? В моем случае я хочу настроить свой объект Log :: Log4perl из файла конфигурации, который указан в моем основном файле конфигурации.

Ответы [ 2 ]

0 голосов
/ 01 мая 2018

Если инициализация действительно взаимозависима, у вас есть проблема, поскольку один из атрибутов обязательно должен быть инициализирован раньше другого. Но ничто в вашем описании не поддерживает это. Похоже, что для создания логгера требуется файл конфигурации, и все.

Просто сделайте создание logger ленивым, давая config шанс быть установленным.

package Class;

use Moose;

has config => ( ... );

has logger => (
    isa     => 'Str',
    is      => 'ro',
    lazy    => 1,
    default => sub {
        my $self = shift;
        my $config = $self->config
            or die(...);

        return Log::Log4perl->get_logger( $config->{logger} );
    },
    handles => [qw( info warn error fatal )],
);

Пример использования

my $o = Class->new( config => "..." );
$o->warn("...");

или

# Assuming config isn't required=>1.
my $o = Class->new();
$o->config("...");
$o->warn("...");
0 голосов
/ 01 мая 2018

Вы можете использовать модификатор метода before (перехват метода), чтобы заставить атрибуты строить в определенном порядке:

package Z;
use Moose;

has config => (
    isa     => 'HashRef',
    is      => 'ro',
    lazy    => 1,
    default => sub { print STDERR "called 'config'\n"; return { a => 'b' }; },
);

has logger => (
    isa     => 'Str',
    is      => 'ro',
    lazy    => 1,
    default => sub { print STDERR "called 'logger'\n"; return 'Fred'; }
);

before 'logger' => sub {
    my $self = shift;
    print STDERR "called before 'logger'\n";
    die "No logger!: $!\n" if !defined $self->config;
    return;
};

package A;

my $z = Z->new();

print "logger: ", $z->logger, "\n";
print "config{a}: ", $z->config->{a}, "\n";

Вывод этого примера кода, показывающий, что config создается до logger с помощью модификатора метода before:

called before 'logger'
called 'config'
called 'logger'
logger: Fred
config{a}: b
...