我知道如何在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;
}
}
现在有没有办法在Perl
中覆盖carp
模块中的croak cluck confess carp
?
Carp 提供的函数只是常规函数,当模块use
d 时,它们会通过导出器导入到您的包中。诀窍是在任何人导入它们之前,在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
,但它应该有效。