2012-10-01 164 views
4

我正在使用遺留代碼,並且必須使用require .pl文件來定義子foo。我的問題是在我的main::命名空間中已經有另一個子foo,稍後在我目前沒有處理的程序的一部分中調用它。如何防止在Perl中覆蓋子?

我需要的文件定義了sub foo {},因爲它顯然不希望foo的東西在它通常被調用的地方發生。就我而言,這很糟糕。

我已經試過玩弄的*foo水珠:

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

當然,因爲我只是創建了一個別名(不工作布賴恩d FOY指出的133頁掌握Perl),因此*old_foo將指向現在的'空'子例程。

有沒有辦法以某種方式將*foo{CODE}中的內容複製到其他位置而不是別名?或者有另一種方法可以解決這個問題嗎?

+0

您可以在自己的名稱空間中重新定義你自己的'foo'(帶包成'包礦;子富{} ...包爲主;'例如,然後調用它應用了這個命名空間限定符? – raina77ow

+0

@ raina77ow:第一個'foo'完全來自其他地方,它不是我的,它只是需要調用它打印頁面的頁腳,但我沒有影響力但是如果它被一個空的子網取代,那麼我的網頁底部會丟失,這有點像被你的褲子夾住了;-) – simbabque

+0

不,我已經談到了你可以改變的'foo'的命名空間,而不是另一個。 ) – raina77ow

回答

3

嘗試這樣

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

這實際上比我自己的解決方案清晰得多。我會切換到這個。非常感謝! – simbabque

3

自己弄明白了。我必須使用typeglob的CODE部分,而不是將整個typeglob分配給另一個typeglob。這樣它似乎會製作一份副本。

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

布賴恩·d FOY也掌握的Perl談論這個(131F頁),但沒有提到複製的一部分。

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: ".([email protected] || $!); 
1; 

這裏我用do,因爲如果在其他地方所需要的代碼require什麼都不做。 (我們有醜陋require "//path/to/code.pl"因爲這個!)

這樣你就可以決定是否通過use Foo qw(foo);use Foo qw(bar);加載foo

UPDATE:哦,你最好計算路徑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; 

這是給你(和你的團隊)雖然。

+0

謝謝。這當然是需要思考的問題。我會在這個方向進行調查。 – simbabque