这行perl代码是什么意思



我有一个perl-mason文件,其中一行看起来像这样:

$result = PI::Membership::Service->cancel(name => $name)

这到底是什么意思?它在调用另一个模块吗?它是面向对象的perl代码吗?

感谢

它用三个参数调用(调用)子例程PI::Membership::Service::cancel

  1. "PI::Membership::Service"
  2. "name"
  3. $name

给定正常的命名约定,这是在包PI::Membership::Service中调用一个名为cancel的子例程,该子例程在@INC路径上的某个名为PI/Membership/Service.pm的文件中定义(然而,有许多异常的命名约定),因此不能保证您会找到这样的文件。如果PI::Membership::Service包(类)继承自一个或多个其他包,则cancel子例程实际上可能在其中一个包中定义。

更多详细信息,请参阅perlobj

除非$resultPi::Membership::Service对象,否则它实际上不是一个面向对象的调用,因为它既不是在创建也不是在操作对象。一个面向对象的调用看起来是这样的:

my $obj = Foo::Bar->new;   #Creating an object of class `Foo::Bar`
$obj->Baz                  #Calling method "Baz" on object "$obj";

看起来这是一个对象样式的调用,用于访问另一个包中的子例程,该子例程尚未导出

要了解实际情况,您必须了解命名空间。Perl使用命名空间。大多数时候,您可能没有意识到这一点,因为您使用的是main的默认命名空间。名称空间是必需的,因为您可能会导致(尤其是在4.x之前的Perl版本中)函数和变量名称冲突。下面是我用旧的Perl3.x风格编写的一个程序:

require "fribulate.pl";
$value = 4.5;
$new_value = fribulate($value);
print "Fribulated Value = $new_value  Original value = $valuen";

这是我的fribulate.pl程序:

sub fribulate {
    my $param = shift;
    $value = $param * 2;
    return $value * 6;
}
1;

当我运行程序时,我得到:

 Fribulated Value = 54. Original Value = 9

等等?最初不是4.5吗?fribulate.pl程序影响了我的$value,因为它还使用了一个名为$value的变量。为了解决这个问题,Perl创建了package命令,该命令创建了一个新的名称空间:

package Fribulate;
sub fribulate {
    my $param = shift;
    $value = $param * 2;
    return $value * 3.1416;
}
1;

现在,fribulate.pl程序不在命名空间main中,而是在命名空间Fribulate中。因此,fribulate.pl中使用的$value变量与我的$value变量不同。

但是,如果我在另一个名称空间中预先加上名称空间,我就可以访问它:

require "fribulate.pl";
$value = 4.5;
$new_value = fribulate($value);
print "Fribulated Value = $new_value  Original value = $valuen";
# Printing the value of $value from frimbulate.pl:
print "And in fribulate.pl, it's using $Fribulate::valuen";

如果使用"文件:查找",您会看到此情况。要访问文件的全名,请使用$File::Find::name。要访问文件的目录,请使用$File::Find::dir。名称空间File::Find是为File::Find中的$dir$name变量准备的。

名称空间的问题是,现在所有的东西都在新的名称空间中,包括我在frimbulate.pl中的frimbulate函数。因此,我的原始程序还必须在函数前面预先设置名称空间才能工作:

require "fribulate.pl";
$value = 4.5;
$new_value = Frimbulate::fribulate($value);
print "Fribulated Value = $new_value  Original value = $valuen";

为了解决这个问题,你在frimbulate.pl程序中做了一个小动作:

Package Frimbulate;
require Exporter;
@EXPORT = qw(frimbulate);
sub fribulate {
    my $param = shift;
    $value = $param * 2;
    return $value * 3.1416;
}
1;

Exporter包在@EXPORT中的函数上撒上了魔法精灵尘1,并使它们可用于main命名空间——所有内容所在的默认命名空间。因此,像File::Copy和File::Basename这样的模块使用Exporter来访问它们各自的copybasename子例程,而无需在它们前面预先准备包名。

这现在被认为是糟糕的样式,因为您可能会在没有任何警告的情况下覆盖具有相同名称的其他子例程。在编写模块的新样式中,您不再自动导出@EXPORT数组中的所有函数。你会在File::Path中注意到这一点,它不会在没有我们明确请求的情况下自动将函数导出到main命名空间。相反,你将它们放在@EXPORT_OK中,这需要用户要求将它们推送到命名空间:

Frimbulate套餐

Package Frimbulate;
require Exporter;
@EXPORT_OK = qw(frimbulate); #You have to request the frimbulate subroutine
sub fribulate {
    my $param = shift;
    $value = $param * 2;
    return $value * 3.1416;
}
1;

我的程序:

# Now I have to ask that the frimbulate subroutine be import into my main namespace
require "fribulate.pl" qw(frimbulate);
$value = 4.5;
$new_value = fribulate($value);
print "Fribulated Value = $new_value  Original value = $valuen";

现在,这将为您提供足够的背景知识来阅读Perl模块文档,并很可能了解发生了什么。Perlmod文档涵盖了名称空间、符号表,甚至还有一些关于变量范围的内容。它包含了很多信息,如果没有基本信息,可能会有点吓人。


1使用Exporter模块时,没有像素受到伤害。如果查看使用perldoc -l Exporter命令可以找到的Exporter.pm,您会发现它直接操作符号表。

相关内容

  • 没有找到相关文章

最新更新