我知道如何在perl
中的内置函数中进行重写,并且我已经重写了die
warn
say
,并且由于无法重写print
和printf
,因此将其与日志框架的句柄绑定(bind)在一起。
覆盖warn
的示例:
BEGIN{ *CORE::GLOBAL::warn = sub {
my ($package, $filename, $line, $subroutine) = caller;
untie *STDERR;
my $message;
foreach my $arg (@_) {
$message = $message.$arg;
}
print STDERR $message;
tie *STDERR, __PACKAGE__, (*STDERR);
logmessage("warn",$message,$filename, $line);
return;
}
}
现在有什么方法可以覆盖
croak cluck confess carp
中的carp
模块中的Perl
吗? 最佳答案
Carp提供的功能只是常规功能,当模块为use
d时,它们会通过Exporter导入到您的包中。技巧是在任何人都可以导入它们之前,在Carp
命名空间内尽早覆盖它们。然后,当他们这样做时,他们会得到覆盖的。
在您的脚本中,或者在您自己的日志记录模块的最顶部:
BEGIN {
require Carp;
# save original croak (will create closure ...)
my $original_croak = \&Carp::croak;
no warnings 'redefine';
*Carp::croak = sub {
print "Croaking...\n"
or $original_croak->("cannot fake croak"); # (... here)
};
}
您需要加载一次Carp,以便Perl解析代码并将函数安装在
Carp
命名空间中。然后,您可以覆盖它们。稍后,在代码中的其他模块中:
use Carp 'croak';
croak 'foo';
现在将产生我们上面设置的输出。
如果要在新代码中调用原始的
Carp::croak
,请将其保存到coderef中,并如上例所示将其保留。请注意,这仅在替换发生得很早时才有效。如果将其放在自己的日志记录模块中,并且在Carp加载后加载,它将失败。
package Foo;
use Carp;
use Your::Logging::Framework;
croak 'foo';
将不起作用,因为在您覆盖
Carp::croak
的位置,Foo::croak
已经是原始Carp::croak
的副本。如果您想完成这项工作,则始终可以将自己的
carp
,croak
等也明确地导入调用者。这会在strict
下引发一堆警告或抱怨,但它应该可以工作。