Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl。OOP脚本中的重复代码_Perl_Oop - Fatal编程技术网

Perl。OOP脚本中的重复代码

Perl。OOP脚本中的重复代码,perl,oop,Perl,Oop,我正在构建一个脚本,需要一些关于重复代码的帮助 这是我的构造器: sub new { my $class = shift; my $self = { ip => shift, username => shift, password => shift, need_enable => 0,

我正在构建一个脚本,需要一些关于重复代码的帮助

这是我的构造器:

sub new {
    my $class = shift;
    my $self = {
                  ip          => shift,
                  username    => shift,
                  password    => shift,
                  need_enable => 0,
                  enable => '',
    };
    my $session = Net::Telnet->new( Timeout => 2, Errmode => 'return');         
    $self->{session} = $session;

   bless($self, $class);
}
sub new {
    my $class      = shift;
    my $ip         = shift;
    my $username   = shift;
    my $password   = shift;

    my $self = {};
    bless $self, $class;

    $self->ip($ip);
    $self->username($username);
    $self->password($password);
    $self->need_enable(0);
    $self->enable('');

    my $session = Net::Telnet->new( Timeout => 2, Errmode => 'return' );
    $self->session($session);

    return $self;
}
以下是一些方法:

sub _send_enable {
    my $self = shift;
    my $session = $self->{session};
    ...

sub _command {
    my $self = shift;
    my $session = $self->{session};
    my $command = shift;
    ...

sub _match_prompt {
    my $self = shift;
    my $session = $self->{session};
    my ( $prematchU , $matchU ) =
         $session->waitfor(match => '/(?m:^[\w.-]+\s?(?:\(config[^\)]*\))?\s?[\$#>]\s?(?:\(enable\))?\s*$)/',
                                        Timeout => 10);
    return  ($prematchU,$matchU);
}
如您所见,在这些方法中,我需要调用构造函数中初始化的telnet实例

我得到了更多的方法,在这些方法中,我需要再次调用telnet实例

此外,我需要在方法内部调用一些方法。我总是需要将对象作为第一个参数:

_command($self, 'show privilege');

_check_enable($self);
也许我遗漏了一些我在“中间Perl”中学到的东西,我只是觉得我可以避免所有重复的代码


谢谢你的建议

第一件事。这:

_command($self, 'show privilege');

_check_enable($self);
这是非常错误的。要在Perl中调用方法,需要使用

$self->_command( 'show privilege' );
$self->_check_enable();
(在第二行中,您可以省略参数,因为参数列表为空。)

->
操作符告诉Perl您希望调用一个方法而不是常规子例程。如果左边的东西是一个受祝福的引用,那么它被祝福的包将用于查找该方法。否则,左边的东西被假定为类名。无论是哪种情况,Perl都会将左侧的内容作为第一项放入参数列表中

使用
->
和直接调用子例程之间的重要区别在于
->
语法导致Perl查找该类或父类中的方法。直接调用子例程不会经过方法分派器

至于访问对象本身,Perl中的标准约定是

my $self = shift;
但这不是必需的。由于方法的参数位于常规的
@
参数数组中,因此可以使用
$[0]
。您也可以对会话对象使用
$\u0]{session}
。但是,如果你把它解压成一个命名的变量,它会更整洁,更容易阅读

如果要避免重复键入定义
$self
,可以使用类似的方法,为您提供一个奇特的
方法
关键字,为您解包
$self

因此:

sub _command {
    my $self = shift;
    my $session = $self->{session};
    my $command = shift;
    ...
变成这样:

method _command( $message ) { 
    # $self and $message are already defined, so just use them
    ...

第一件事。这:

_command($self, 'show privilege');

_check_enable($self);
这是非常错误的。要在Perl中调用方法,需要使用

$self->_command( 'show privilege' );
$self->_check_enable();
(在第二行中,您可以省略参数,因为参数列表为空。)

->
操作符告诉Perl您希望调用一个方法而不是常规子例程。如果左边的东西是一个受祝福的引用,那么它被祝福的包将用于查找该方法。否则,左边的东西被假定为类名。无论是哪种情况,Perl都会将左侧的内容作为第一项放入参数列表中

使用
->
和直接调用子例程之间的重要区别在于
->
语法导致Perl查找该类或父类中的方法。直接调用子例程不会经过方法分派器

至于访问对象本身,Perl中的标准约定是

my $self = shift;
但这不是必需的。由于方法的参数位于常规的
@
参数数组中,因此可以使用
$[0]
。您也可以对会话对象使用
$\u0]{session}
。但是,如果你把它解压成一个命名的变量,它会更整洁,更容易阅读

如果要避免重复键入定义
$self
,可以使用类似的方法,为您提供一个奇特的
方法
关键字,为您解包
$self

因此:

sub _command {
    my $self = shift;
    my $session = $self->{session};
    my $command = shift;
    ...
变成这样:

method _command( $message ) { 
    # $self and $message are already defined, so just use them
    ...
我的模块旨在消除PerlOO中的重复。这里有一个例子

use Moops;
use Net::Telnet;

class My::Class :ro {
  has ip          => ();
  has username    => ();
  has password    => ();
  has need_enable => (default => 0);
  has enable      => (default => '');
  has session     => (builder => 1);

  method BUILDARGS ($ip, $username, $password) {
    return {
      ip       => $ip,
      username => $username,
      password => $password,
    };
  }

  method _build_session () {
    Net::Telnet->new(Timeout => 2, Errmode => 'return');
  }

  method _send_enable () {
    my $session = $self->session;
    ...;
  }

  method _command ($command) {
    my $session = $self->session;
    ...;
  }

  method _match_prompt () {
    $self->session->waitfor(
      match   => '/(?m:^[\w.-]+\s?(?:\(config[^\)]*\))?\s?[\$#>]\s?(?:\(enable\))?\s*$)/',
      Timeout => 10,
    );
  }
}
我的模块旨在消除PerlOO中的重复。这里有一个例子

use Moops;
use Net::Telnet;

class My::Class :ro {
  has ip          => ();
  has username    => ();
  has password    => ();
  has need_enable => (default => 0);
  has enable      => (default => '');
  has session     => (builder => 1);

  method BUILDARGS ($ip, $username, $password) {
    return {
      ip       => $ip,
      username => $username,
      password => $password,
    };
  }

  method _build_session () {
    Net::Telnet->new(Timeout => 2, Errmode => 'return');
  }

  method _send_enable () {
    my $session = $self->session;
    ...;
  }

  method _command ($command) {
    my $session = $self->session;
    ...;
  }

  method _match_prompt () {
    $self->session->waitfor(
      match   => '/(?m:^[\w.-]+\s?(?:\(config[^\)]*\))?\s?[\$#>]\s?(?:\(enable\))?\s*$)/',
      Timeout => 10,
    );
  }
}

您可以消除
my$self=shift。毕竟,这只是
$\u0]
。您可以简单地使用
$\u0]>{session}
而不是不断地执行
my$session=$self->{session}
。这也会解决一些接受问题

但是,这种重复性对于文档编制非常有用。当我看到
my$self=shift
子定义下,我立即知道这是一个方法,而不是构造函数或普通子程序

当我编写方法和构造函数时,我的前几行获取参数。我还对构造函数和方法隐藏结构或对象。这确实意味着要多写几行代码,但这些代码有助于记录我正在尝试做的事情。这是一个捕捉可能错误的好方法,或者帮助可怜的schlub维护和调试我的代码

例如,下面是我如何创建构造函数:

sub new {
    my $class = shift;
    my $self = {
                  ip          => shift,
                  username    => shift,
                  password    => shift,
                  need_enable => 0,
                  enable => '',
    };
    my $session = Net::Telnet->new( Timeout => 2, Errmode => 'return');         
    $self->{session} = $session;

   bless($self, $class);
}
sub new {
    my $class      = shift;
    my $ip         = shift;
    my $username   = shift;
    my $password   = shift;

    my $self = {};
    bless $self, $class;

    $self->ip($ip);
    $self->username($username);
    $self->password($password);
    $self->need_enable(0);
    $self->enable('');

    my $session = Net::Telnet->new( Timeout => 2, Errmode => 'return' );
    $self->session($session);

    return $self;
}
这需要更多的写作,也许你会称之为重复,但是

  • 第一行告诉您这是一个构造函数(
    my$class=shift;
  • 接下来的三行告诉您,我希望有三个参数按这个顺序排列
  • 没有迹象表明我的对象实际上是如何存储的。相反,我使用方法来设置每个字段——这是许多真正的面向对象语言所坚持的。这可能意味着我有更多的方法,但也意味着如果我必须修改我的类的结构,我不必修改每个构造函数或方法
下面是我的
会话
方法的样子:

my session {
    my $self     = shift;
    my $session  = shift;

    if ( defined $session ) {
        if ( not $self->isa("Net::Telnet") ) {
            croak qq(Session parameter must be a "Net::Telnet" object.);
        }
        $self->{session} = $session;
    }
    return $self->{session};
}
这是我代码中唯一提到会话信息如何实际存储在对象中的地方。通过创建一个单独的方法来设置/获取会话,我可以进行一些测试。例如,我想测试会话是否是
Net::Telnet
对象。如果我决定改变会话在对象中的存储方式,这是代码中唯一需要触摸的地方

当然,现在我有很多你想消除的重复:

sub _command {
    my $self    = shift;
    my $command = shift;

    my $session = $self->session;
    ...
接受我在answ开始时提出的建议