任何人都可以在Perl中解释(我的$ self = shift)

时间:2013-10-03 14:29:02

标签: perl attributes self shift moose

我很难理解OO Perl和my $self = shift;的交集这些单独元素的文档很棒,但我发现它们都没有触及它们的工作原理在一起。

我一直在使用Moose制作带有属性的模块,当然,在所述模块中引用模块的属性也很有用。我已经被一遍又一遍地告诉我在子程序中使用my $self = shift;来将模块的属性分配给该变量。这是有道理和有效的,但是当我也将参数传递给子例程时,此过程显然采用@ARGV数组的第一个元素,并将其分配给$self

有人可以解释我如何使用shift来获取对模块属性的内部访问权限,同时还传递@ARGV数组中的参数吗?

3 个答案:

答案 0 :(得分:58)

首先,子程序未通过@ARGV数组。而是将传递给子例程的所有参数展平为子例程内@_表示的单个列表。 @ARGV数组位于脚本的顶层,包含传递给脚本的命令行参数。

现在,在Perl中,当您在对象上调用方法时,该对象将作为参数隐式传递给方法。

如果忽略继承,

 $obj->doCoolStuff($a, $b);

相当于

 doCoolStuff($obj, $a, $b);

这意味着方法@_doCoolStuff的内容将是:     @_ = ($obj, $a, $b);

现在,shift内置函数(没有任何参数)将元素移出默认数组变量@_。在这种情况下,那将是$obj

因此,当您执行$self = shift时,您实际上是在说$self = $obj

我也希望这能解释如何通过->表示法将其他参数传递给方法。继续我上面提到的例子,这就像:

sub doCoolStuff {
  # Remember @_ = ($obj, $a, $b)
  my $self = shift;
  my ($a, $b) = @_;

此外,虽然Moose是Perl的一个很棒的对象层,但它并没有消除您需要在每个方法中自己初始化$self的要求。永远记住这一点。虽然像C ++和Java这样的语言隐式初始化对象引用this,但在Perl中你需要为你编写的每个方法显式地执行它。

答案 1 :(得分:8)

在顶级代码中,shift()shift(@ARGV)的缩写。 @ARGV包含命令行参数。

在子版中,shift()shift(@_)的缩写。 @_包含sub的参数。

所以my $self = shift;抓住了sub的第一个参数。调用方法时,调用者(->的左侧)将作为第一个参数传递。换句话说,

$o->method(@a)

类似于

my $sub = $o->can('method');
$sub->($o, @a);

在该示例中,my $self = shift;会将$o分配给$self

答案 2 :(得分:2)

如果你打电话:

$myinstance->myMethod("my_parameter");  

与做:

相同
myMethod($myinstance, "my_parameter");  

但如果你这样做:

myMethod("my_parameter");  

仅限#34; my_parameter"将被通过。

然后如果你在myMethod里面总是这样做:

 $self = shift @_;  
当从对象上下文中调用myMethod id时, $ self将成为对象引用 但将是" my_parameter"当从程序的方式从内部的另一个方法调用时 请注意这一点;