通过另一个使用它的类从类调用方法

时间:2017-10-19 21:03:52

标签: perl oop

创建了一个Perl模块:

use ElectricCommander;
use strict;
use warnings;

package EC;

sub new
{
   my $class = shift;
   my $server = shift;
   my $self = {};
   bless( $self, $class );
   $self->{EC} = ElectricCommander->new($server);
   $self->{EC}->login("user", "password");
   return $self;
}
1;

在脚本中,有没有办法调用ElectricCommander模块中的方法? 例如,电子控制器中存在getJobStatus,我可以执行下面的操作吗?

use EC;
$obj = EC->new("myserver");
$obj->getJobDetails("1234");

3 个答案:

答案 0 :(得分:1)

只需将以下内容添加到EC包中:

sub getJobDetails { shift->{EC}->getJobDetails(@_) }

如果您有多种类型的方法,则可以使用动态构建包装器。

BEGIN {
   for my $method_name (qw( getJobDetails ... )) {
      my $local_method = sub { shift->{EC}->$method_name(@_) };

      no strict qw( refs );
      *$method_name = $local_method;
   }
}

您甚至可以将所有来电重定向到EC中不存在的方法,如下所示:

use Carp qw( croak );

sub AUTOLOAD {
    my $method_name = our $AUTOLOAD;
    $method_name =~ s/^.*:://s;
    return if $method_name eq 'DESTROY';

    my $remote_method = $_[0]->can($method_name)
       or croak(sprintf("Can't locate object method \"%s\" via package \"%s\"", $method_name, ref($_[0])));

    my $local_method = sub { shift->{EC}->$remote_method(@_) };

    no strict qw( refs );
    *$method_name = $local_method;
    goto &$method_name;
}

答案 1 :(得分:1)

这里的组合似乎很合适:将方法添加到EC以分派给其他类的方法。

例如

package EC;

use strict;
use warnings;

use ElectricCommander;

sub new { 
    ...
    $self->{EC} = ElectricCommander->new($server);
    ...
}

sub getJobDetails {
    my ($self, @args) = @_;
    $self->{EC}->getJobDetails(@args);
}

你可以致电

use EC;
my $ec_obj = EC->new(...);
$ec_obj->getJobDetails(...);

您还可以将ElectricCommander实例化为class data,而不是new,以便ECuse时,其对象构建一次。这是一个设计选择,无论您是希望EC个实例都有自己的ElectricCommander对象,根据需要构建,或者一个对象是否符合所有EC对象的需求。

如果EC要真正扩展ElectricCommander - 要使用它的大多数方法,重写一些并添加更多 - 那么你可以让它继承自ElectricCommander的<子类。 / p>

大多数情况下,你需要在另一个你想要的合成中使用一个类,如上所示,一个类使用另一个类的功能( has-a relationship )。当您构建一个经过深思熟虑的类层次结构时,继承是合适的,其中父级放置更多的一般或抽象行为,而其子类主要专门化它(是一种关系)。

答案 2 :(得分:1)

ElectricCommander实例可以使用EC的所有方法的最简单方法是将EC作为ElectricCommander的子类:

package EC;
use strict;
use warnings;

use parent 'ElectricCommander';

sub new
{
   my $class = shift;
   my $self = $class->SUPER::new(@_);
   $self->login("user", "password");
   return $self;
}

1;

现在

use EC;
my $obj = EC->new("myserver");
$obj->getJobDetails("1234");

应该工作(tm)。