Should I set inheritance at compile time and not at run time, and if so, why?

Perl AFAIK inheritance is usually configured as follows:

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

Are there any examples where use base (or use parent ) is better?

+6
inheritance perl
source share
3 answers

Establishing compilation inheritance avoids the particularly complex dependency debugging cycle shown below.

 # 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; 

If you "use Child" before "use Foo", then Foo will try to call Child->wibble before it sets its inheritance to Mother . If Child was to use parent qw(Mother) instead, its inheritance would be established before it tries to load anything else.

I was such a loop of dependencies in private corporate code, which tends to be slightly interwoven than regular code. This sucks for debugging, so I recommend always setting inheritance at compile time.

+3
source share
 use base qw(Horse Donkey); 

This is roughly equivalent to:

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

This is more accurate if you need to download the code of the modules, as well as inherit from them. By the way, there are problems with multiple inheritance, but that's another question :)

Edit: Benefits of compilation time v. lead time:

  • You have the security of checking compile time using a database, meaning that your script will not even start if your base module is missing from the file system.
  • If you want to decide to use this module at run time, you can test and add the module to your parents:

    if (eval {require X}) {push @ISA, 'X'; }

+5
source share

Regarding compilation time-vs-run-time:

In Perl, modules (packages / namespaces) usually live in separate files. That is, Some::Module can be found in Some / Module.pm. In this setting, the difference in compilation time vs-run-time will not make much difference. The runtime of the module loaded using use() will be until the call code is compiled. Observer:

File Some/Module.pm :

 package Some::Module; BEGIN{ print "Some::Module - compile time\n" } print "Some::Module - run time\n"; 1; 

File test.pl :

 BEGIN{ print "Just started compiling the program.\n" } use Some::Module; BEGIN{ print "main - compile time\n" } print "main - run time\n"; 

The output will be:

 Just started compiling the program. Some::Module - compile time Some::Module - run time main - compile time main - run time 

Therefore, before compilation of your main program will continue after loading the module, our @ISA = qw(Base); .

It is true, however, that assigning @ISA does not guarantee that the base class has been loaded. That is why we have the use base and use parent pragmas. If you do not need any use base functions (fields) and do not need the longer backward compatibility that it provides in use parent , I suggest you use the lighter use parent .

+1
source share

All Articles