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开始时提出的建议