Perl - 子例程重新定义

use*_*757 27 perl subroutine

我之前已经问过这个问题或者搜查过其他人问过 - 为什么我收到警告" 子程序mySub重新定义在../lib/Common.pm第x行 "?并且你总是得到你在同一个代码中声明sub两次的答案.我创建了这个测试包:

整个文件---------------

package MyCommonPkg;

use strict;

sub thisSubroutineIsNotDefinedAnywhereElse{
}

1;
Run Code Online (Sandbox Code Playgroud)

整个文件---------------

我使用perl脚本使用这个包,它使用其他包,也使用这个包,我得到警告:

子程序ThisSubroutineIsNotDefinedAnywhereElse在../lib/MyCommonPkg.pm第19行重新定义.

我保证我没有在其他地方声明这个子.这是由循环引用引起的吗?如何跟踪此警告的原因并进行修复?

Gra*_*ean 34

你有依赖循环吗?如果Perl开始编译脚本并遇到如下所示的行:

use PackageA;
Run Code Online (Sandbox Code Playgroud)

Perl暂停编写脚本; 找到PackageA.pm并开始编译它.如果遇到这样的一行:

use PackageB;
Run Code Online (Sandbox Code Playgroud)

Perl暂停编译PackageA; 找到PackageB.pm并开始编译它.通常,这将成功完成,Perl将返回完成编译PackageA,当成功完成时,它将返回编译脚本,当成功完成时,它将开始执行已编译的操作码.

但是,如果PackageB.pm包含以下行:

use PackageA;
Run Code Online (Sandbox Code Playgroud)

您可能期望它不会做任何事情,因为Perl已经处理了PackageA.pm,但问题是它还没有完成.所以Perl将暂停PackageB的编译并从头开始再次开始编译PackageA.pm.这可能会触发您在重新定义PackageA中的子例程时看到的消息.

作为一般规则,两个包不应相互依赖.然而,有时循环更难定位,因为它是由第三个包引起的.

  • 我认为这是我的问题 - 如何解决呢?它不是循环引用 - 我会看到循环引用,因为PackageA"使用PackageB;" 和PackageB有"使用PackageA;" 相反,我有一个脚本"main.pl"使用PackageA并使用PackageB,而PackageA也使用PackageB.这应该不是什么问题? (3认同)

小智 24

如果在不同的包中有两个具有相同名称的子例程,则应该看到此警告(启用警告时)为"Subroutine new redefined ....".一个简单的原因(非常接近Grant McLean所说的,但仍然不完全正确)是你必须让你的包跳过编译阶段然后再需要.这样,Perl命名空间管理器在编译时将找不到任何具有相同名称的冲突符号,如果模块没有任何错误,那么它们之后也会正常工作.

只要确保你实施

需要模块;

声明而不是

使用模块;

你不应该再看到这个警告.

  • 不同包中具有相同名称的子组件是可以的。Perl 不会对此发出警告 - 这就是包的要点:) (2认同)

hob*_*bbs 7

如果您使用的是具有不区分大小写的文件系统(Windows,通常是OSX)的系统,并且您use Common在一个文件和use common另一个文件中执行,则可能会导致此类问题.


Eri*_*son 7

这听起来像是由循环依赖引起的问题。这是跟踪它的方法。如果您的问题类如下所示:

package AlientPlanet;
use Dinosaurs;
sub has_dinosaurs {...}
1;
Run Code Online (Sandbox Code Playgroud)

然后将您的示例更改为如下所示:

package AlienPlanet;
sub has_dinosaurs {...}     # <-- swap
use Dinosaurs;              # <-- swap
1;
Run Code Online (Sandbox Code Playgroud)

现在用Carp::Always编译你的代码,如下所示:

? perl -MCarp::Always -c lib/AlienPlanet.pm                                                                                                            
Subroutine has_dinosaurs redefined at lib/AlienPlanet.pm line 4.
    require AlienPlanet.pm called at lib/Dinosaurs.pm line 4
    Dinosaurs::BEGIN() called at lib/AlienPlanet.pm line 4
    eval {...} called at lib/AlienPlanet.pm line 4
    require Dinosaurs.pm called at lib/AlienPlanet.pm line 5
    AlienPlanet::BEGIN() called at lib/AlienPlanet.pm line 4
    eval {...} called at lib/AlienPlanet.pm line 4
lib/AlienPlanet.pm syntax OK
Run Code Online (Sandbox Code Playgroud)

现在你有了一个堆栈跟踪,你可以看到循环在哪里。快速而肮脏的解决方案是在 Dinosaurs.pm 中使用Class::Load

有关更详细的解释,请尝试我的博客文章