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

问题描述 投票:28回答:3

我很难理解OO Perl和my $self = shift;的交叉点关于这些单独元素的文档很棒,但我发现它们都没有触及它们如何协同工作。

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

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

perl attributes self shift moose
3个回答
59
投票

首先,子程序不通过@ARGV数组。相反,传递给子程序的所有参数都被扁平化为子程序中由@_表示的单个列表。 @ARGV数组位于脚本的顶层,包含传递给您脚本的命令行参数。

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

如果忽略继承,

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

相当于

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

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

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

所以当你做$self = shift时,你实际上是在说$self = $obj

我也希望这解释了如何通过q​​azxswpoi表示法将其他参数传递给方法。继续我上面提到的例子,这将是:

->

另外,虽然sub doCoolStuff { # Remember @_ = ($obj, $a, $b) my $self = shift; my ($a, $b) = @_; 是Perl的一个很好的对象层,但它并没有消除你需要在每个方法中自己初始化Moose的要求。永远记住这一点。虽然像C ++和Java这样的语言隐式初始化对象引用$self,但是在Perl中你需要为你编写的每个方法显式地执行它。


8
投票

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

在一个子,@ARGVshift()的缩写。 shift(@_)包含sub的参数。

所以@_正在抓住该子的第一个论点。调用方法时,调用者(my $self = shift;的左边)作为第一个参数传递。换一种说法,

->

类似于

$o->method(@a)

在那个例子中,my $sub = $o->can('method'); $sub->($o, @a); my $self = shift;分配给$o


2
投票

如果你打电话:

$self

这样做:

$myinstance->myMethod("my_parameter");  

但如果你这样做:

myMethod($myinstance, "my_parameter");  

只有“我的参数”才能通过。

那么如果在myMethod里面,你总是这么做:

myMethod("my_parameter");  

从对象上下文调用方法时,$ self将成为对象引用 但是当从程序方式中的另一个方法调用时,它将是“我的参数”。 要注意这一点;

© www.soinside.com 2019 - 2024. All rights reserved.