有人能用Perl解释一下(我的$self=shift)吗

有人能用Perl解释一下(我的$self=shift)吗,perl,attributes,self,shift,moose,Perl,Attributes,Self,Shift,Moose,我很难理解OOPerl和我的$self=shift的交集关于这些单独元素的文档非常棒,但我发现它们中没有一个涉及到它们是如何协同工作的 我一直在使用Moose制作具有属性的模块,当然,在所述模块中引用模块的属性是很有用的。我一次又一次地被告知要使用my$self=shift以将模块的属性分配给该变量。这是有意义的,并且是有效的,但是当我也向子例程传递参数时,这个过程显然会获取@ARGV数组的第一个元素,并将其分配给$self 有人能解释一下我如何使用shift获得对模块属性的内部访问,同时在@A

我很难理解OOPerl和我的$self=shift的交集关于这些单独元素的文档非常棒,但我发现它们中没有一个涉及到它们是如何协同工作的

我一直在使用Moose制作具有属性的模块,当然,在所述模块中引用模块的属性是很有用的。我一次又一次地被告知要使用
my$self=shift以将模块的属性分配给该变量。这是有意义的,并且是有效的,但是当我也向子例程传递参数时,这个过程显然会获取
@ARGV
数组的第一个元素,并将其分配给
$self


有人能解释一下我如何使用shift获得对模块属性的内部访问,同时在
@ARGV
数组中传递参数吗?

首先,子例程不会在
@ARGV
数组中传递。相反,传递给子例程的所有参数都被展平到子例程内部由
@
表示的单个列表中。@ARGV数组位于脚本的顶层,包含传递给脚本的命令行参数

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

如果你忽略了继承

 $obj->doCoolStuff($a, $b);
相当于

 doCoolStuff($obj, $a, $b);
这意味着方法
docooltuff
@
的内容将是:
@=($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这样的语言隐式地初始化对象引用<代码> < <代码>,但是在Perl中,您需要对每一个编写的方法显式地执行它。

在顶层代码中,<代码> SHIVTHER()/<代码>是<>代码> SHIFT(@ ARGV)。code>@ARGV
包含命令行参数

在sub中,
shift()
shift(@\ux)
的缩写<代码>@
包含sub的参数

所以
my$self=shift
正在获取sub的第一个参数。调用方法时,invocant(
->
的剩余部分)作为第一个参数传递。换句话说,

$o->method(@a)
类似于

my $sub = $o->can('method');
$sub->($o, @a);
在该示例中,
my$self=shift会将
$o
分配给
$self

$myinstance->myMethod("my_parameter");  
与执行以下操作相同:

myMethod($myinstance, "my_parameter");  
但如果你这样做了:

myMethod("my_parameter");  
将只传递“my_参数”

然后,如果在myMethod中始终执行以下操作:

 $self = shift @_;  
从对象上下文调用myMethod id时,$self将成为对象引用
但当以过程方式从内部的另一个方法调用时,将是“my_参数”。

意识到这一点

shift
如果从子例程内部调用,则默认为
@
;如果从顶级代码调用,则默认为
@ARGV
。@cjm没错。我会在回答中提到。太棒了。那太有帮助了。我确实遇到了一个问题,$self=shift似乎将自己设置为我实际传递到子例程的第一个参数。也就是说,@u中的第一个元素不是对象,但实际上是我提供的第一个参数。发生这种情况的高层次原因是什么?(我已经解决了这个问题,没有实际的代码了)当您不确定Perl var输出中包含什么时,请使用Data::Dumper模块输出内容。@AlexHHadik我只能想象这种情况会发生的一种情况。当您没有像下面这样通过对象调用方法时:
$obj->method($arg1,$arg2)
您错过了对象,直接调用了方法
method($arg1,$arg2)
。这在Perl中是完全合法的,因为方法调用与普通函数调用没有什么不同。但是,由于您没有使用
->
操作符通过对象调用它,
$obj
参数不会传递给arg列表中的方法。