Perl 如何确保方法调用在正确的对象上使用正确的方法名称?

Perl 如何确保方法调用在正确的对象上使用正确的方法名称?,perl,methods,Perl,Methods,我正在编写一个程序,该程序会多次尝试处理,每次尝试时(之前/之后的其他几个步骤)都会存储到一个新日志中 而不是: perl PerlLocalMethod.pl Entering into log 0: Processing 0 Entering into log 1: Processing 1 Entering into log 1: Processing 2 我认为问题在于,在我第一次调用Process方法时,Logger方法是“编译”的,我在第一次调用时使用了对象引用,但之后没有。 如

我正在编写一个程序,该程序会多次尝试处理,每次尝试时(之前/之后的其他几个步骤)都会存储到一个新日志中

而不是:

perl PerlLocalMethod.pl 
Entering into log 0: Processing 0
Entering into log 1: Processing 1
Entering into log 1: Processing 2
我认为问题在于,在我第一次调用Process方法时,Logger方法是“编译”的,我在第一次调用时使用了对象引用,但之后没有。
如果我做了$logger->Print(),拼错了Print,并点击了一个我无法可靠测试的代码路径(这是针对嵌入式系统的,我不能强制每个错误条件),它会用一个未定义的方法错误输出脚本。我想我可以在logger中使用AUTOLOAD并记录任何错误的方法调用,但我想知道关于如何确保logger()调用可靠并使用正确对象的任何其他建议

在Perl中,子例程是在编译时编译的。将命名的子例程声明嵌入到子例程中不会达到预期效果,因此不建议这样做

如果你害怕打字错误,就编写测试。看看如何做。如果无法在开发人员机器上实例化系统特定的类,请使用模拟。或者使用较短的名称,如
P

您可以将最高范围内的记录器声明为$Logger上的闭包,您也需要在此处声明:

my $logger;
sub Logger { $logger->Print($_[0]) }

但是,如果有许多这样的变量和子例程,这会让人困惑,并且会导致代码更难维护。

如果您在代码中使用了
使用警告,您会看到以下消息:

变量“$logger”不会在记录器第24行保持共享

这会提醒您注意这个问题(寓意是:始终
使用严格的
使用警告

我不完全清楚为什么您需要这么多级别的子例程来进行日志记录,但在我看来,所有将
$logger
对象作为其第一个参数的子例程可能都应该通过
MyLoggerObject
(它可能应该被称为
MyLoggerClass
,因为它是一个类,而不是一个对象)

如果您这样做,那么您将得到以下代码(这似乎是您想要的):


哦,请注意,我已经从间接对象表示法调用(
newclass(…)
)转移到稍微更安全的
Class->new(…)
。您使用的样式在绝大多数情况下都有效,但如果不起作用,您将浪费数天时间试图解决问题。

如上所述,在此类方法中使用词汇定义的变量是不可能的

如果你必须“管道胶带”解决这个问题,你可以使用全局变量(我们的而不是我的)


但是请注意,$logger和$thingToLog现在是可在此函数之外访问的全局变量。

谢谢。我将研究mocking,我非常喜欢使用p.Plus Autoload至少记录错误调用的想法。要点(如果我理解的话)是为了在子例程名称中输入错误时获得编译时错误。在编译时不会检查方法。请始终使用
use strict;使用warnings;
。这会对您有所帮助。
perl PerlLocalMethod.pl 
Entering into log 0: Processing 0
Entering into log 1: Processing 1
Entering into log 1: Processing 2
my $logger;
sub Logger { $logger->Print($_[0]) }
use strict;
use warnings;

for my $i (0 .. 2) {
    my $loggerObject = MyLoggerClass->new(tag => $i);
    #.. do a bunch of other things ..
    $loggerObject->Process($i);
    #.. do a bunch of other things ..
}



package MyLoggerClass;

sub new {
    my $package = shift;
    my $self = { @_ };
    return bless $self, $package;
}

sub Process {
    my $self = shift;
    my ($thingToLog) = @_;

    $self->Logger("Processing $thingToLog");
}

sub Logger {
    my $self = shift;

    $self->Print($_[0]);
}

sub Print {
   my $self = shift;
   my ($value) = @_;

   print "Entering into log $self->{tag}: $value\n";
}

1;
sub Process
{

    our ($logger,$thingToLog) = @_;
    sub Logger { $logger->Print($_[0]); }
    Logger("Processing $thingToLog");

}