【问题标题】:Perl: Changing some methods of a module with use parentPerl:使用父级更改模块的某些方法
【发布时间】:2013-07-09 00:22:23
【问题描述】:

想象一下我有一个 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 时,会以哪个“前缀”方法为准,是我写的新的还是原来的来自父模块?

【问题讨论】:

    标签: perl


    【解决方案1】:

    如果这些方法是函数(注意:不是类的一部分,不是您所做的事情my $instance = Module::Cool->new(); 它不会完全按照您的意愿执行。由父模块导出到您的模块中的子例程将不会被导入使用 use parent 调用到您的命名空间(故意 - 它会破坏 OO),因为“父”模块仅用于扩展对象。如果这些子例程恰好具有类似 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 了解更多信息。

    【讨论】:

      【解决方案2】:

      是的。见: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
      

      【讨论】:

        【解决方案3】:

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

        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的方法时,父母和孩子都会被调用。

        【讨论】:

          【解决方案4】:

          这是一个简单的例子,如果Module::CoolOO

          父类

          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
          

          【讨论】:

            猜你喜欢
            • 2015-10-20
            • 1970-01-01
            • 2017-06-22
            • 2016-02-03
            • 2019-03-01
            • 2020-03-14
            • 1970-01-01
            • 1970-01-01
            • 2012-07-26
            相关资源
            最近更新 更多