Din*_*wda 2 perl overriding carp die
我知道如何覆盖内置的函数perl
,我已经覆盖die
warn
say
,因为print
并且printf
无法覆盖我已将它绑定到我的日志框架的句柄.
覆盖示例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;
}
}
Run Code Online (Sandbox Code Playgroud)
现在我可以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)
};
}
Run Code Online (Sandbox Code Playgroud)
您需要加载Carp一次,以便Perl解析代码并在Carp
命名空间中安装函数.然后你可以覆盖它们.
稍后,在代码中的其他模块中:
use Carp 'croak';
croak 'foo';
Run Code Online (Sandbox Code Playgroud)
这将产生我们在上面设置的输出.
如果要Carp::croak
在新内容中调用原始内容,请将其保存到coderef并保留,如上例所示.
请注意,这仅在替换发生得非常早时才有效.如果你把它放在你自己的日志模块中,并且在Carp加载后它被加载,这将失败.
package Foo;
use Carp;
use Your::Logging::Framework;
croak 'foo';
Run Code Online (Sandbox Code Playgroud)
无法正常工作,因为在您覆盖的位置Carp::croak
,Foo::croak
已经是原始的副本Carp::croak
.
如果你想做那个工作,你总是可以导入自己的carp
,croak
等等也明确地导入调用者.这将引发一堆警告或抱怨strict
,但它应该工作.