1

想象一下,我有一个 CPAN-ish 模块,我不能让自己直接修改 Module::Cool,它具有 new、communicate_heartbeat、is_running、remove_heartbeat 和 prefix 方法。

我想使用这些方法,但我需要稍微更改“前缀”方法。我听说您可以在本地、服务器等中创建一个文件,例如:

package My::Module::Cool;               

use strict;                              
use warnings;                            
use utf8;                                

use parent qw(Module::Cool);                                                                                                        

1; 

如果我在这里添加一个“子前缀{ ....}”方法,当我尝试使用 My::Module::Cool 时,哪个“前缀”方法将占上风,我写的新方法或来自父级的原始方法模块?

4

4 回答 4

4

如果这些方法是函数(注意:不是类的一部分,不是你做过的事情my $instance = Module::Cool->new();,它不会做你想要的。由父模块导出到你的模块的子例程不会被导入到你的命名空间(故意 -它会破坏 OO)use parent调用,因为“父”模块仅用于扩展对象。如果这些子例程恰好具有类似 OO 的名称,Exporter(用于导出函数的模块)可以解决问题。

首先,您必须将您想要的其他功能带入您的模块(通过导入 - 这是use Cool::Module在导出子例程时无论如何都会在幕后执行的操作),构建您自己的替换功能(如果需要,调用原始功能),然后再次导出所有内容.

这是一个例子:

use strict;
use warnings;
use utf8;

# Make sure this happens at compile time, before anything else in the module
BEGIN {
    require Module::Cool; # make sure it loads, but don't import yet

    # get all the functions you want to normally import
    my @imports = grep { $_ ne 'prefix' } @Module::Cool::EXPORT;

    # Now do the actual import after filtering; see `perldoc use`.
    Module::Cool->import(@imports); 
};

require Exporter;
our @ISA = qw/Exporter/; # The 'Exporter' base class does function exporting
our @EXPORT = @Module::Cool::EXPORT; # same export list

sub prefix
{
    my @args = @_;

    # stuff before calling the original prefix

    Module::Cool::prefix(@_);

    # then do stuff after

    return ...; # and return as before.
}

1;

如果Cool::Module不自动导出,则交换到@EXPORT_OK并使用@EXPORT_OK列表。有关perldoc Exporter更多信息,请参阅。

于 2013-07-09T00:48:14.503 回答
4

是的。参见:perlobj

来自 perlobj:

Method Resolution Order

Method resolution order only matters in the case of multiple inheritance. 
In the case of single inheritance, Perl simply looks up the inheritance 
chain to find a method:

    Grandparent
     |
    Parent
     |
    Child
于 2013-07-09T00:49:11.657 回答
2

如果这些方法是类的一部分,它会正常工作!:-)

PS C:\dev> perl
package My::Base;

use 5.012;
use warnings;

sub new { return bless {}, shift; }
sub frob { say "in base" }

package My::Child;

use 5.012;
use warnings;

use base 'My::Base';

sub frob { say "in child"; }

package main;

my $base = My::Base->new();
$base->frob();

my $child = My::Child->new();
$child->frob();

给出:

in base
in child
PS C:\dev>

要调用父函数,请使用特殊SUPER前缀。将上面的示例修改为:

# in My::Child...   
sub frob {
    my $self = shift; 
    $self->SUPER::frob(); 
    say "in child"; 
}

给...

in base
in base
in child

现在调用 child 的方法时会同时调用 parent 和 child。

于 2013-07-09T00:53:05.647 回答
0

这是一个简单的例子 if Module::Coolis OO

家长班

package TestPackage;

use strict;
use warnings;

sub new {
    my $class = shift;
    my $self = {};

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

    return "TestPackage";
}

sub is_running {
    my $self = shift;

    return "duh";
}

1;

孩子

package TestPackage2;

use warnings; 
use strict;

use base 'TestPackage';

sub prefix {
    my $self = shift;

    return "TestPackage2";
}

1;

一些使用子类的脚本

#!/usr/bin/perl

use strict; 
use warnings;

use TestPackage2;

my $tp2 = TestPackage2->new();

print $tp2->prefix(), "\n";
print $tp2->is_running(), "\n";

输出

$ test.pl
TestPackage2
duh
于 2013-07-09T00:53:45.923 回答