这行perl代码是什么意思?

时间:2013-07-08 18:50:32

标签: perl module mason

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

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

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

由于

2 个答案:

答案 0 :(得分:7)

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

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

    perlobj中的更多详情。

答案 1 :(得分:1)

除非$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中)函数和变量名称冲突。这是我用旧的Perl 3.x风格编写的程序:

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

这是我的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中。因此,$value中使用的fribulate.pl变量与我的$value变量不同。

但是,如果我在其上添加命名空间,我可以访问另一个命名空间中的变量:

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

# Printing the value of $value from frimbulate.pl:
print "And in fribulate.pl, it's using $Fribulate::value\n";

如果您使用File:Find,您会看到这一点。要访问文件的全名,请使用$File::Find::name。要访问文件的目录,请使用$File::Find::dir。名称空间File::Find位于$dir$nameFile::Find个变量的前面。

命名空间的问题是现在所有内容都在新命名空间中,包括frimbulate中的frimbulate.pl函数。因此,我的原始程序还必须在函数前面添加命名空间才能工作:

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

为了解决这个问题,你在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::CopyFile::Basename等模块使用Exporter来允许您访问各自的copybasename子例程,而无需在其前面添加包名称。

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

Frimbulate Package

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 = $value\n";

现在应该为您提供足够的背景资料来阅读Perl Module文档,并且很可能了解正在发生的事情。 Perlmod文档包括名称空间,符号表,甚至包括变量范围。它包含大量信息,如果没有基本信息,可能会有点吓人。


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