Perl 为包添加别名以启用两用名称空间

Perl 为包添加别名以启用两用名称空间,perl,namespaces,Perl,Namespaces,我有一个有趣的情况。在一些(大型)遗留代码中,有一个名称空间看起来应该类似于require a::B,但是添加了a的路径,因此可以只说require B。但是,我希望能够使用这两种调用。这在不创建重定向包的情况下是否可行?例如,是否有一种双重声明包的方法 谢谢 requiresomething将在@INC目录中搜索名为Something.pm的文件。 要获取要加载的some path/A/B.pm或require B或require A::B,您需要在@INC目录列表中同时包含some path

我有一个有趣的情况。在一些(大型)遗留代码中,有一个名称空间看起来应该类似于
require a::B
,但是添加了a的路径,因此可以只说
require B
。但是,我希望能够使用这两种调用。这在不创建重定向包的情况下是否可行?例如,是否有一种双重声明包的方法


谢谢

requiresomething
将在
@INC
目录中搜索名为
Something.pm的文件。
要获取要加载的
some path/A/B.pm
require B
require A::B
,您需要在
@INC
目录列表中同时包含
some path
some path/A


您可以添加目录或以其他方式操作您的
@INC
列表。

首先加载包:

require A::B;
然后别名
B
A::B

*B:: = *A::B::;
然后告诉
require
它已经加载了
B

$INC{'B.pm'}++;
为了确保这一切正常工作,最好在
BEGIN
块中执行以下操作:

BEGIN {
    require A::B;
    *B:: = *A::B::;
    $INC{'B.pm'}++;
}
在此之后,所有
都需要A::B
需要B行将变为无操作。您还可以使用任意名称引用该包中的变量<代码>\&A::B::foo==\&B::foo

要使其透明地工作,可以向每个文件添加以下代码:

  • A/B.pm

    *B:: = *A::B::;
    $INC{'B.pm'}++;
    
    *A::B:: = *B::;
    $INC{'A/B.pm'}++;
    
    *B:: = *A::B::;  # this gets added to the existing file
    $INC{'B.pm'}++;
    
    require A::B;  # this is the entire file
    
  • B.pm

    *B:: = *A::B::;
    $INC{'B.pm'}++;
    
    *A::B:: = *B::;
    $INC{'A/B.pm'}++;
    
    *B:: = *A::B::;  # this gets added to the existing file
    $INC{'B.pm'}++;
    
    require A::B;  # this is the entire file
    
然后,如果用户
需要a::B
他们可以调用
A::B::foo
B::foo
要求B将成为禁止操作

如果用户
需要B
他们可以调用
A::B::foo
B::foo
要求A::B将成为禁止操作

但是对于可维护性,最好将所有真实代码保存在一个文件中(以及上面的别名代码),并将另一个文件设置为仅加载真实文件的垫片。假设
A/B.pm
包含真实代码:

  • A/B.pm

    *B:: = *A::B::;
    $INC{'B.pm'}++;
    
    *A::B:: = *B::;
    $INC{'A/B.pm'}++;
    
    *B:: = *A::B::;  # this gets added to the existing file
    $INC{'B.pm'}++;
    
    require A::B;  # this is the entire file
    
  • B.pm

    *B:: = *A::B::;
    $INC{'B.pm'}++;
    
    *A::B:: = *B::;
    $INC{'A/B.pm'}++;
    
    *B:: = *A::B::;  # this gets added to the existing file
    $INC{'B.pm'}++;
    
    require A::B;  # this is the entire file
    

Eric的解决方案是可行的,但老实说,我会枪毙任何在实际生产代码中这样做的人。通过使用中的方法,您可能会获得类似的结果,但是,为什么还要像这样将符号表搞得一团糟呢?我宁愿修复以错误方式调用东西的遗留代码。说真的,搜索并替换代码并修复包名有多难

另一种快速而肮脏的获取
的方法需要B要实际查找包A::B,只需在lib/目录中创建一个指向A/B.pm的符号链接:

cd lib
ln -sf -T A/B.pm B.pm

请注意,这将创建两个具有相同代码的包,因此其中一个包中的变量值与另一个包中的变量值不同:
$A::B::foo
将与
$B::foo
完全分离,即使它们的声明来自同一个文件。

,我应该补充一点,我没有出于技术原因而使用
use
。这些可能是什么技术原因?你知道
require
use
有多相似吗?问题是这就是当前的情况,require是有效的。也许我应该澄清一下,我希望能够以两种方式调用对包的调用<代码>A::B::foo()
B::foo()
这花了我一段时间才理解,但非常好。以太-(1)有时,不可能更改遗留代码(例如,电源会因为一些受诅咒的混乱而抖动),唯一的解决办法是解决问题;(2) 尽管任何人经常进行这样的黑客行为都会造成不良后果,但这样一种方法即使在生产环境中也有其有效的用途,即使这种方法已被很好地记录在案,并且理想情况下不再需要。非常小心。我承认,它仍然有味道。=>符号链接解决方案将创建一个包含大量子例程重新定义的警告的包,并可能导致功能错误。这是因为每个包都包含相同的
包XXX行。