【问题标题】:How can I prevent a sub being overwritten in Perl?如何防止在 Perl 中覆盖 sub?
【发布时间】:2012-10-01 09:15:24
【问题描述】:

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

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

我尝试过使用*foo glob:

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

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

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

【问题讨论】:

  • 你能在你自己的命名空间中重新定义你自己的foo吗(例如将它包装到package Mine; sub foo {} ... package main;中,然后应用这个命名空间限定符来调用它?
  • @raina77ow:第一个 foo 完全来自其他地方。它甚至不是我的,它只是需要被调用。它打印网页的页脚,但我对它没有影响。但是,如果它被一个空子代替,我的网页底部就会丢失,这感觉有点像被你的裤子抓住了。 ;-)
  • 不,我已经谈到了命名空间'foo'你可以改变,而不是另一个。 )
  • @raina77ow:谢谢你的想法。在另一个required 文件中,该文件超出了我的控制范围,该文件在应用程序的大多数部分中都在使用。我不明白我怎么能改变它。 :-/

标签: perl subroutine typeglob


【解决方案1】:

这样试试

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

【讨论】:

  • 这实际上比我自己的解决方案要清晰得多。我会切换到这个。非常感谢!
【解决方案2】:

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

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

brian d foy 在 Mastering Perl(第 131f 页)中也谈到了这一点,但没有提到复制部分。

【讨论】:

    【解决方案3】:

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

    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"!)

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

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

    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;
    

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

    【讨论】:

    • 谢谢。这当然是值得考虑的事情。我会朝这个方向调查。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-19
    • 2021-02-08
    • 2014-05-19
    • 2020-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多