如何防止在Perl中覆盖子?

时间:2012-10-01 09:15:25

标签: perl subroutine typeglob

我正在使用遗留代码,并且必须require定义子foo的.pl文件。我的问题是在我的main::命名空间中已经存在另一个子foo,稍后在我目前没有处理的程序的一部分中调用它。

我需要的文件定义sub foo {},因为很明显它不希望foo在通常被调用的地方发生。就我而言,这很糟糕。

我试过玩*foo glob:

*old_foo = *foo;
require 'foo_killer.pl';
*foo = *old_foo;

当然,这不起作用,因为我只创建了一个别名(正如brian d foy指出掌握Perl 的第133页),因此*old_foo将指向现在是'空'子程序。

有没有办法以某种方式将*foo{CODE}中的内容复制到其他地方而不是别名呢?或者可能有另一种解决方法吗?

3 个答案:

答案 0 :(得分:3)

自己想出来。我必须使用typeglob的CODE部分,而不是将整个typeglob分配给另一个typeglob。这样它似乎可以复制。

*old_foo = *foo{CODE};
require 'foo_killer.pl';
*foo = *old_foo{CODE};

brian d foy也在 Mastering Perl (第131页)中讨论了这个问题,但未提及复制部分。

答案 1 :(得分:3)

试试这个

{
    local *foo;
    require 'foo_killer.pl';
}

答案 2 :(得分:2)

我建议一劳永逸地将邪恶的遗留代码包装到一个包中。

package Foo;
use strict; 
use warnings;

use Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw(foo bar $evil $global $variables);

do "foo_killer.pl"
     or die "Failed to load foo_killer.pl: ".($@ || $!);
1;

我在这里使用do,因为require如果其他地方需要代码则不会执行任何操作。 (因为这个,我们有丑陋的require "//path/to/code.pl"!)

这样您就可以决定是通过foo还是use Foo qw(foo);加载use Foo qw(bar);

更新哦,您最好计算foo_killer.pl相对于__FILE__的路径,而不是按绝对路径加载:

my $foo_killer = __FILE__; # $LIB/Foo.pm
$foo_killer =~ s,(/+[^/]+),legacy,; # $LIB/legacy
$foo_killer .= "foo_killer.pl"; # $LIB/legacy/foo_killer.pl
# now do $foo_killer;

这取决于你(和你的团队)。