使用 BUILDARGS 替换角色中的 class
Using BUILDARGS to substitute a class in a Role
我使用 Perl Moose Role (Import::Git::Role
) 作为抽象基础 Class 在 Class 和实际功能实现 (Import::Git
) 之间共享共同行为和执行一些日志记录的 Class (Import::Git::dryrun
)。
我希望试运行 class 是透明的。我想创建一个这样的对象:
my $git = Import::Git->new( dryrun => $dryrun );
变量 dryrun 可以是 0 或 1。如果是 1,我想构造一个 Import::Git::dryrun
对象,基本上用它替换 Import::Git
对象。那是因为他们通过角色共享所有方法。
我试过在 BUILDARGS 方法中像这样交换对象:
around BUILDARGS => sub {
my $orig = shift;
my $class = shift;
my %args = ( @_ == 1 ? %{ $_[ 0 ] } : @_ );
if ( !%args || $args{ 'dryrun' } != 1 ) {
return $class->$orig( @_ );
}
else {
return Import::Git::dryrun->$orig( @_ );
}
};
但这并没有实现我想要做的,它构建了旧的 class:
DB<1> x Import::Git->new( dryrun => 1 )
0 Import::Git=HASH(0x2fd9210)
'dryrun' => 1
DB<2> x Import::Git->new()
0 Import::Git=HASH(0x301dbb8)
'dryrun' => 0
DB<3>
我想我可能不得不调用 dryrun-method 的新方法,所以我做了以下交换:
# change this:
return Import::Git::dryrun->$orig( @_ );
# to this
return Import::Git::dryrun->new( @_ );
但是 returns BUILDARGS did not return a HASH reference
.
我错过了什么?
BUILDARGS
用于在创建对象之前操作您传递给对象构造函数的参数列表,因此不会影响 new returns。你可能想尝试 around new
而不是 around BUILDARGS
,然后你可以用干的 运行 对象替换 new 返回的对象。
让构造函数构建与所请求的不同的 class 是很恶心的。即使它确实有效,我也不会采用您所做的方法。我会用
sub factory {
my ($class, %opts) = @_;
return $opt{dryrun} ? $class.'::dryrun' : $class;
}
Import::Git->factory( dryrun => $dryrun )->new( ... )
或
sub instantiate {
my ($class, %opts) = @_;
return ( delete($opt{dryrun}) ? $class.'::dryrun' : $class )->new(%opts);
}
Import::Git->instantiate( dryrun => $dryrun, ... )
我使用 Perl Moose Role (Import::Git::Role
) 作为抽象基础 Class 在 Class 和实际功能实现 (Import::Git
) 之间共享共同行为和执行一些日志记录的 Class (Import::Git::dryrun
)。
我希望试运行 class 是透明的。我想创建一个这样的对象:
my $git = Import::Git->new( dryrun => $dryrun );
变量 dryrun 可以是 0 或 1。如果是 1,我想构造一个 Import::Git::dryrun
对象,基本上用它替换 Import::Git
对象。那是因为他们通过角色共享所有方法。
我试过在 BUILDARGS 方法中像这样交换对象:
around BUILDARGS => sub {
my $orig = shift;
my $class = shift;
my %args = ( @_ == 1 ? %{ $_[ 0 ] } : @_ );
if ( !%args || $args{ 'dryrun' } != 1 ) {
return $class->$orig( @_ );
}
else {
return Import::Git::dryrun->$orig( @_ );
}
};
但这并没有实现我想要做的,它构建了旧的 class:
DB<1> x Import::Git->new( dryrun => 1 )
0 Import::Git=HASH(0x2fd9210)
'dryrun' => 1
DB<2> x Import::Git->new()
0 Import::Git=HASH(0x301dbb8)
'dryrun' => 0
DB<3>
我想我可能不得不调用 dryrun-method 的新方法,所以我做了以下交换:
# change this:
return Import::Git::dryrun->$orig( @_ );
# to this
return Import::Git::dryrun->new( @_ );
但是 returns BUILDARGS did not return a HASH reference
.
我错过了什么?
BUILDARGS
用于在创建对象之前操作您传递给对象构造函数的参数列表,因此不会影响 new returns。你可能想尝试 around new
而不是 around BUILDARGS
,然后你可以用干的 运行 对象替换 new 返回的对象。
让构造函数构建与所请求的不同的 class 是很恶心的。即使它确实有效,我也不会采用您所做的方法。我会用
sub factory {
my ($class, %opts) = @_;
return $opt{dryrun} ? $class.'::dryrun' : $class;
}
Import::Git->factory( dryrun => $dryrun )->new( ... )
或
sub instantiate {
my ($class, %opts) = @_;
return ( delete($opt{dryrun}) ? $class.'::dryrun' : $class )->new(%opts);
}
Import::Git->instantiate( dryrun => $dryrun, ... )