我有一个Perl程序并打包Worker
和Log
。
Worker几乎完成所有计算,我想通过引用Worker子例程以及一些其他参数(标量和数组)来传递一个对象。我见过this和this等示例。
他们通过将@_
置于子中,然后操纵对象来处理此问题。我还找到了一种使用索引来操纵它们的方法,比如@{$_[i]}
。问题是,当我尝试这样的代码时,我收到一个错误:
Can't call method "write" on unblessed reference at ...
以下代码段。
主:
use strict;
use warnings;
use Log;
use Worker;
my $log = Log->new();
my $worker = Worker->new();
my $scalar = "SomeURLhere";
my @array = ('red','blue','white');
# I do some stuff with $log object
#...
# Now I want to pass data to the Worker
$worker->subFromWorker($scalar, \$log, \@array);
use strict;
use warnings;
package Worker;
sub new {
my $class = shift;
my $self = {};
bless $self, $class;
return $self;
}
sub subFromWorker{
my ($self) = shift;
my $scalar = $_[0];
#my ($log) = $_[1];
my @array = @{$_[2]};
foreach my $item (@array){
print $item;
}
$_[1]->write("The items from url $scalar are printed.");
#Same thing happens if I use $log here
}
在C#中,这是以不同的方式处理的 - 您可以通过值或引用将参数发送到方法,然后在专门的方法中执行您想要的操作(预编写方法以通过引用处理参数或值)。我认为在Perl中使用\parameter
发送将发送引用。
答案 0 :(得分:6)
对象是引用。参考是标量值。
如果要将数组或散列传递给子例程,那么通常需要传递对它们的引用 - 因为Perl参数传递对标量值的效果要好得多。
但$log
已经是对象的引用。因此,您不需要参考它。您最终传递了对引用的引用。因此,当您将该参数复制到子例程中的$log
时,您将获得额外的,不必要的引用级别。
修复方法是将$log
标量传递给子例程。
$worker->subFromWorker($scalar, $log, \@array); # $log, not \$log
其他一切都会正常工作。
答案 1 :(得分:3)
您已阅读有关阻止您的计划工作的问题,但您还应了解其他一些事项
Perl词法标识符和子例程/方法名称由字母数字和下划线组成。大写字母保留用于全局标识符,例如Worker
和Log
等包名。
您use
或require
的文件包应以语句1;
结尾,以便在导入时返回 true 值,否则你的程序可能无法编译。
如果您正在编写的子程序恰好是方法,那么最好通过移开$self
参数并复制其余部分来启动它。 :
my $self = shift;
my ($p1, $p2, $p3) = @_;
很少直接使用@_
的元素,除非您急需最低速度奖金
通常最好直接使用数组引用而不是复制数组,特别是如果它可能很大。
以下是我对程序和相关模块进行编码的方法:
use strict;
use warnings;
use Worker;
use Log;
my $log = Log->new;
my $worker = Worker->new;
my $scalar = 'SomeURLhere';
my @array = qw/ red blue white /;
$worker->worker_method($scalar, $log, \@array);
use strict;
use warnings;
package Worker;
sub new {
my $class = shift;
my $self = {};
bless $self, $class;
return $self;
}
sub worker_method {
my $self = shift;
my ($scalar, $log, $array) = @_;
foreach my $item (@$array) {
print $item, "\n";
}
$log->write("The items from URL $scalar are printed.");
}
1;
use strict;
use warnings;
package Log;
sub new {
my $class = shift;
bless {}, $class;
}
sub write {
my $self = shift;
my ($text) = @_;
print "Logging: $text\n"
}
1;
red
blue
white
Logging: The items from URL SomeURLhere are printed.
答案 2 :(得分:0)
更常见的模式是使用List赋值将@_
解压缩为多个变量:
sub subFromWorker {
my ($self, $scalar, $log_ref, $array) = @_;
...
}
参考您的具体问题:
my $log = Log->new();
$log
已对您的对象的引用,使用\$log
创建对该引用的引用,这可能不是您想要的。您可以通过以下两种方式处理:
$log
:
$worker->subFromWorker($scalar, $log, \@array);
$log
中取消引用subFromWorker
:
$$log_ref->write('...');