Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/selenium/4.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中,我可以只向包的一个对象动态添加方法吗?_Perl_Monkeypatching_Www Mechanize - Fatal编程技术网

在Perl中,我可以只向包的一个对象动态添加方法吗?

在Perl中,我可以只向包的一个对象动态添加方法吗?,perl,monkeypatching,www-mechanize,Perl,Monkeypatching,Www Mechanize,我正在与自动化基于web的后台办公室合作,单击我需要执行的操作,以使我的测试电子商务订单达到我需要的状态,从而测试我对一个长的、由多个部分组成的工作流的特定部分所做的更改。要批量处理大量订单,我需要经常单击主页链接。为了缩短时间,我在运行时在WWW::Mechanize中嵌入了一个方法,如下所示,这是基于brian d foy在《掌握Perl》中的一个示例: { # Shortcut to go back to the home page by calling $mech->go_home

我正在与自动化基于web的后台办公室合作,单击我需要执行的操作,以使我的测试电子商务订单达到我需要的状态,从而测试我对一个长的、由多个部分组成的工作流的特定部分所做的更改。要批量处理大量订单,我需要经常单击主页链接。为了缩短时间,我在运行时在WWW::Mechanize中嵌入了一个方法,如下所示,这是基于brian d foy在《掌握Perl》中的一个示例:

{ # Shortcut to go back to the home page by calling $mech->go_home
  # I know I'll get a warning and do not want it!
  no warnings 'once';
  my $homeLink = $mech->find_link( text => 'Home' )->url_abs();
  $homeLink =~ s/system=0/system=1/;
  *WWW::Mechanize::go_home = sub {
    my ($self) = @_;
    return $self->get($homeLink);
  };
}
这非常有效,不会伤害任何人,因为我正在使用它的脚本只供我使用,并且不是更大系统的一部分

但是现在我想知道是否有可能只告诉一个$mech对象有这个方法,而另一个WWW::Mechanize对象可能稍后创建,比如说,在不混淆另一个具有到我的后台的活动会话的对象的情况下进行交叉引用,却不能使用这个方法

我不确定这是否可行,因为如果我理解对象在Perl中的工作方式,->操作符会告诉它在包WWW::Mechanize中查找子例程go_home,并将$mech作为第一个参数传递给它。如果这种理解是错误的,请纠正我

我通过添加一种硬编码检查进行了实验,该检查只允许原始$mech对象使用该函数

my $onlyThisMechMayAccessThisMethod = "$mech";
my $homeLink = $mech->find_link( text => 'Home' )->url_abs();
$homeLink =~ s/system=0/system=1/;
*WWW::Mechanize::go_home = sub {
  my ($self) = @_;
  return undef unless $self eq $onlyThisMechMayAccessThisMethod;
  return $self->get($homeLink);
};
由于$mech包含存储数据的地址,例如WWW::Mechanize=HASH0x2fa25e8,因此以这种方式字符串化时,另一个对象的外观会有所不同

然而,我不相信这是一条路要走。所以我的问题是:有没有更好的方法只让WWW::Mechanize类的一个对象拥有这个方法?我也很高兴听到关于此代码的其他建议。

这只是

$mech->follow_link(text => 'Home')
我不认为它的特殊性足以保证它自己的方法,或者需要限制到一个唯一的对象俱乐部

还值得注意的是,在不同的包中声明子例程时,不需要使用typeglobs。例如,你只需要写作

sub WWW::Mechanize::go_home {
    my ($self) = @_;
    return $self->get($homeLink);
};
但一般的解决方案是,只将那些您希望使用新方法的对象作为子类并声明为成员

文件MyMechanize.pm

文件test.pl

这只是

$mech->follow_link(text => 'Home')
我不认为它的特殊性足以保证它自己的方法,或者需要限制到一个唯一的对象俱乐部

还值得注意的是,在不同的包中声明子例程时,不需要使用typeglobs。例如,你只需要写作

sub WWW::Mechanize::go_home {
    my ($self) = @_;
    return $self->get($homeLink);
};
但一般的解决方案是,只将那些您希望使用新方法的对象作为子类并声明为成员

文件MyMechanize.pm

文件test.pl


为什么不为那些需要额外方法的实例创建子类WWW::Mechanize并实例化该子类?或者更好,编写一个包装新的WWW::Mechanize::Pluggable插件,以便您可以在实例化时指定该对象应具有的附加功能。为什么不将WWW::Mechanize子类化,并为需要附加方法的实例实例化该子类?或者更好,编写一个包装新内容的WWW::Mechanize::Pluggable插件,以便您可以在实例化时指定该对象应具有的附加功能。@daxim:您能解释一下您对使用父对象的偏好吗?如果您选择这样做,那么前面的用法WWW::Mechanize是多余的。应该首选parent,因为它是在开始时间。正确,它已经加载了导入列表中名为的模块。@daxim:找到了。它也更有表现力。你改变了我。首先,谢谢你的解释。我今天就试试。关于主页链接,它不仅仅是一个$mech->follow_linktext=>'home',因为不是每个页面都有一个糟糕的链接,而且参数系统有两种状态可以根据我所在的子区域进行切换,但是我总是需要它为1。@simbabque:从这个意义上说,如果找不到指定的链接并且不尝试获取,follow\u link会返回undf,因此更有用。@daxim:您能解释一下您使用父对象的偏好吗?如果您选择这样做,那么前面的用法WWW::Mechanize是多余的。应该首选parent,因为它是在开始时间。正确,它已经加载了导入列表中名为的模块。@daxim:找到了。它也更有表现力。你改变了我。首先,谢谢你的解释。我今天就试试。关于主页链接,它不仅仅是一个$mech->follow_linktext=>'home',因为不是每个页面都有一个糟糕的链接,而且参数系统有两种状态可以根据我所在的子区域进行切换,但是我总是需要它为1。@simbabque:从这个意义上说,follow_link更有用,因为如果找不到指定的链接并且不尝试获取,它将返回undf。