我有一个perl mason文件,其中一行看起来像这样:
$result = PI::Membership::Service->cancel(name => $name)
究竟是什么意思?它是在调用另一个模块吗?它是面向对象的perl代码吗?
由于
答案 0 :(得分:7)
它使用三个参数调用(调用)子例程PI::Membership::Service::cancel
。
"PI::Membership::Service"
"name"
$name
给定正常的命名约定,这是在cancel
包中调用一个名为PI::Membership::Service
的子例程,该子例程在PI/Membership/Service.pm
路径上的某个名为@INC
的文件中定义(有但是,许多异常的命名约定,所以不能保证你会找到这样的文件)。如果PI::Membership::Service
包(类)继承自一个或多个其他包,则cancel
子例程实际上可能在其中一个包中定义。
perlobj
中的更多详情。
答案 1 :(得分:1)
除非$result
是Pi::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
中$name
和File::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::Copy和File::Basename等模块使用Exporter
来允许您访问各自的copy
和basename
子例程,而无需在其前面添加包名称。
现在这被认为是错误的样式,因为你最终可能会覆盖其他具有相同名称的子程序,而不会发出任何警告。在新的编写模块样式中,您不再自动导出@EXPORT
数组中的所有函数。您会在File::Path中注意到这一点,如果没有我们明确请求它,它不会自动将其函数导出到main
命名空间。相反,您将它们放在@EXPORT_OK
中,要求用户要求将它们推入命名空间:
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
,您会看到它直接操作符号表。