简体   繁体   English

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

[英]Perl Moose with multiple mutually-dependent attributes

How can I create my Perl Moose class such that multiple mutually-dependent attributes are built in the proper order? 如何创建我的Perl Moose类,以便以正确的顺序构建多个相互依赖的属性? In my case, I want to configure my Log::Log4perl object from a configuration file that is specified in my main configuration file. 在我的例子中,我想从我的主配置文件中指定的配置文件配置我的Log :: Log4perl对象。

If the initialization is truly mutually-dependent, you have a problem, since one of the attributes must necessarily be initialized before the other. 如果初始化确实是相互依赖的,那么就会出现问题,因为其中一个属性必须先于另一个属性进行初始化。 But nothing about your description supports this. 但是你的描述没有任何支持。 It sounds like creating the logger requires the config file, and that's it. 这听起来像创建记录器需要配置文件,就是这样。

Just make the creation of logger lazy, giving config a chance to be set. 只需创建logger lazy,给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 )],
);

Sample usage 样品用法

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

or 要么

# Assuming config isn't required=>1.
my $o = Class->new();
$o->config("...");
$o->warn("...");

You can use the before method modifier (method hook) to force the attributes to build in a specific order: 您可以使用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";

The output of this sample code, showing that config is built before logger via the before method modifier: 此示例代码的输出,显示config是在logger之前通过before方法修饰符构建的:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM