Perl Moose具有多个相互依赖的属性

时间:2018-05-01 14:44:27

标签: perl attributes moose

如何创建Perl Moose类,以便以正确的顺序构建多个相互依赖的属性?在我的例子中,我想从我的主配置文件中指定的配置文件配置我的Log :: Log4perl对象。

2 个答案:

答案 0 :(得分:8)

如果初始化确实是相互依赖的,那么就会出现问题,因为其中一个属性必须先于另一个属性进行初始化。但是你的描述没有任何支持。这听起来像创建记录器需要配置文件,就是这样。

只需创建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("...");

答案 1 :(得分:1)

您可以使用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