我应该在编译时而不是运行时建立继承,如果是这样,为什么?

时间:2010-02-13 11:30:37

标签: perl inheritance

Perl中的AFAIK继承通常设置如下:

package Mule;
our @ISA = ("Horse", "Donkey");

是否有use base(或use parent)更好的示例?

3 个答案:

答案 0 :(得分:5)

use base qw(Horse Donkey);

这大致相当于:

BEGIN {
    require Horse;
    require Donkey;
    push @ISA, qw(Horse Donkey);
}

如果您需要加载模块代码以及继承模块代码,它会更整洁。顺便说一句,有多重继承的问题,但这是一个不同的问题:)

编辑:编译时v。运行时优势:

  • 您可以使用 use base 进行编译时检查的安全性,这意味着如果文件系统中没有基本模块,您的脚本甚至都无法启动。
  • 如果您想在运行时决定使用给定的模块,那么您可以测试并将模块添加到您的父母:

    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 baseuse parent pragma的原因。如果您不特别需要use base(字段)的任何功能,也不要求use parent提供更长的向后兼容性,我建议您使用更轻量级的use parent