如何继承具有相同名称但位于不同库位置的类?

huangapple go评论91阅读模式
英文:

How to inherit a class with the same name but in a different lib location?

问题

I'm working with Perl and facing a challenge where I need to inherit a class with the same name (same package name) but located in different lib paths.

It seems like Perl only sees the package name and doesn't consider the lib paths when resolving inheritance. I tried manipulating @INC to change the order of the lib paths, but it hasn't helped.

Has anyone encountered this problem before or have any thoughts on how to inherit from a module with the same name but located in a different lib path?

Thanks in advance.

Samuel

Here's what I've attempted:

I've organized my modules like this:

  • Kernel::Module1 in the main directory.
  • Another Kernel::Module1 in the Custom/ directory.

In my main.pl code, I've included:

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

And inside the module in /Custom, I tried:

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

Unfortunately, Perl returns the error: "Class 'Kernel::Module1' tried to inherit from itself."

英文:

I'm working with Perl and facing a challenge where I need to inherit a class with the same name (same package name) but located in different lib paths.

It seems like Perl only sees the package name and doesn't consider the lib paths when resolving inheritance. I tried manipulating @INC to change the order of the lib paths, but it hasn't helped.

Has anyone encountered this problem before or have any thoughts on how to inherit from a module with the same name but located in a different lib path?

Thanks in advance.

Samuel

Here's what I've attempted:

I've organized my modules like this:

  • Kernel::Module1 in the main directory.
  • Another Kernel::Module1 in the Custom/ directory.

In my main.pl code, I've included:

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

And inside the module in /Custom, I tried:

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

Unfortunately, Perl returns the error: "Class 'Kernel::Module1' tried to inherit from itself."

答案1

得分: 2

不能有两个具有相同(包)名称的模块。


您有两个遵循此模式的文件:

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::Module1的用户获取其修改后的版本,您将需要采用猴子补丁。

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->();   # 可选择调用原始子程序/方法。

      ...
   };

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

1
英文:

You can't have two modules with the same (package) name.


You have two files that follow this pattern:

package Kernel::Module1;

...

sub some_sub_or_method { ... }

...

This is basically equivalent to

package Kernel::Module1;

...

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

...

So loading/executing the two files will result in

package Kernel::Module1;

...

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

...

package Kernel::Module1;

...

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

...

The second assignment will undo the first. You can't have two modules with the same (package) name.


If you want users of Kernel::Module1 to get a modified version of it, you will need to resort to 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

答案2

得分: 1

@ikegami的答案引导我使用了Class::Monkey库,这使我能够在不产生错误的情况下调用原始方法:

.\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
英文:

@ikegami answer led me to a solution using Class::Monkey lib which allowed me to call the original method without errors:

.\main.pl:

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

use lib &#39;.&#39;;
use lib &#39;./Custom&#39;;

use Kernel::Module1Patch;

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

print $module1-&gt;subRoutine();

.\Kernel\Module1:

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

use strict;
use warnings;

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

sub subRoutine {
  return &quot;original&quot;;
}
1;

.\Custom\Kernel\Module1Patch:

package Kernel::Module1Patch;

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

1;

Return result:

aroundoriginal

huangapple
  • 本文由 发表于 2023年8月11日 03:43:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/76878869.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定