perl 如何继承一个同名但位于不同库位置的类?

6kkfgxo0  于 2023-10-24  发布在  Perl
关注(0)|答案(2)|浏览(169)

我正在使用Perl,面临着一个挑战,我需要继承一个具有相同名称(相同包名)但位于不同lib路径的类。
看起来Perl在解析继承时只看到包名而不考虑库路径。我试过操纵@INC来改变库路径的顺序,但没有用。
有没有人以前遇到过这个问题,或者对如何从一个同名但位于不同库路径的模块继承有什么想法?
先谢了。
塞缪尔
以下是我的尝试:
我把我的模块组织成这样:

  • 主目录中的Kernel::Module 1。
  • Custom/目录中的另一个Kernel::Module 1。

在我的main.pl代码中,我包含了:

use lib '.';
use lib './Custom';
use Kernel::Module1;

在/Custom中的模块中,我尝试:

{
  local @INC = ('.', @INC);
  use base 'Kernel::Module1';
}

不幸的是,Perl返回错误:“Class 'Kernel::Module 1' tried to inherit from itself”。

5n0oy7gb

5n0oy7gb1#

不能有两个模块具有相同的(包)名称。
您有两个遵循此模式的文件:

package Kernel::Module1;

...

sub some_sub_or_method { ... }

...

这基本上相当于

package Kernel::Module1;

...

BEGIN { *some_sub_or_method = sub { ... }; }

...

因此,加载/执行这两个文件将导致

package Kernel::Module1;

...

BEGIN { *some_sub_or_method = sub { ... }; }

...

package Kernel::Module1;

...

BEGIN { *some_sub_or_method = sub { ... }; }

...

第二次赋值将撤消第一次赋值。你不能有两个具有相同(包)名称的模块。
如果你想让Kernel::Module 1的用户得到一个修改过的版本,你需要求助于monkey patching。

package My::Patch::Kernel::Module1;

use strict;
use warnings;

use Kernel::Module1 qw( );
use Sub::Name       qw( subname );
 
{
   my $old = \&Kernel::Module1::some_sub_or_method;

   my $new = subname some_sub_or_method => sub {
      ...

      $old->();   # Optionally call original sub/method.

      ...
   };

   no warnings qw( redefine );
   *Kernel::Module1::some_sub_or_method = $new;
}

1
k7fdbhmy

k7fdbhmy2#

@ikegami的回答让我使用Class::Monkey lib来解决这个问题,它允许我调用原始方法而不会出错:
.\main.pl:

#!/usr/bin/perl
use strict;
use warnings;

use lib '.';
use lib './Custom';

use Kernel::Module1Patch;

my $module1 = Kernel::Module1Patch->new();

print $module1->subRoutine();

.\Kernel\Module1:

#!/usr/bin/perl
package Kernel::Module1;

use strict;
use warnings;

sub new {
    my $class = shift;
    return bless {}, $class;
}

sub subRoutine {
  return "original";
}
1;

.\Custom\Kernel\Module1Patch:

package Kernel::Module1Patch;

use Class::Monkey qw<Kernel::Module1>;
 
# The patch
around 'subRoutine' => sub {
    my $originalSubRoutine = shift;
    my $self = shift;
    return 'around' . $self->$originalSubRoutine(@_);
},
qw<Kernel::Module1>;
# /The Patch

1;

返回结果:

aroundoriginal

相关问题