2

我知道如何覆盖内置函数,perl并且我已经覆盖die warn say并且不能被覆盖,我已经将它绑定到我的日志框架的句柄printprintf

覆盖示例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 carpcarp模块中覆盖Perl

4

1 回答 1

6

Carp 提供的函数只是在模块为used 时通过 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::croakFoo::croak已经是原始的副本Carp::croak

如果你想让它工作,你总是可以将你自己的carpcroak等等显式地导入调用者。这会引发一堆警告或在 下抱怨strict,但它应该可以工作。

于 2017-10-09T09:47:28.450 回答