Perl中的AFAIK继承通常设置如下:
package Mule;
our @ISA = ("Horse", "Donkey");
是否有use base
(或use parent
)更好的示例?
答案 0 :(得分:5)
use base qw(Horse Donkey);
这大致相当于:
BEGIN {
require Horse;
require Donkey;
push @ISA, qw(Horse Donkey);
}
如果您需要加载模块代码以及继承模块代码,它会更整洁。顺便说一句,有多重继承的问题,但这是一个不同的问题:)
编辑:编译时v。运行时优势:
如果您想在运行时决定使用给定的模块,那么您可以测试并将模块添加到您的父母:
if(eval {require X}){ 推@ISA,'X'; }
答案 1 :(得分:3)
在编译时建立继承可以避免特别难以调试的依赖循环,如下所示。
# Child.pm
package Child;
our @ISA = qw(Mother);
use Foo;
# Mother.pm
package Mother;
sub wibble { 42 }
# Foo.pm
package Foo;
use Child;
Child->wibble;
如果你在“使用Foo”之前“使用Child”,那么Foo会在Child->wibble
建立继承之前尝试调用Mother
。如果将Child改为use parent qw(Mother)
,则在尝试加载任何其他内容之前,将建立其继承。
我一直是私有公司代码中的这种依赖循环,它往往比公共代码更加交织在一起。调试很糟糕,这就是为什么我建议总是在编译时建立继承。
答案 2 :(得分:1)
关于compile-vs-run-time:
在Perl中,模块(包/命名空间)通常存在于单独的文件中。即可以在Some / Module.pm中找到Some::Module
。在此设置中,编译与运行时差异无关紧要。通过use()
加载的模块的运行时将在调用代码的编译时间之前继续。观察者:
档案Some/Module.pm
:
package Some::Module;
BEGIN{ print "Some::Module - compile time\n" }
print "Some::Module - run time\n";
1;
档案test.pl
:
BEGIN{ print "Just started compiling the program.\n" }
use Some::Module;
BEGIN{ print "main - compile time\n" }
print "main - run time\n";
输出将是:
Just started compiling the program.
Some::Module - compile time
Some::Module - run time
main - compile time
main - run time
因此,在加载模块后继续编译主程序之前,将执行our @ISA = qw(Base);
。
但是,分配给@ISA
并不能确保已加载基类是正确的。这就是我们拥有use base
和use parent
pragma的原因。如果您不特别需要use base
(字段)的任何功能,也不要求use parent
提供更长的向后兼容性,我建议您使用更轻量级的use parent
。