web-dev-qa-db-ja.com

誰でもPerlで説明してください(私の$ self = shift)

OO Perlとmy $self = shift;の交点を理解するのは本当に大変です彼らは一緒に働きます。

私はMooseを使用して属性を持つモジュールを作成してきましたが、もちろん、そのモジュール内でモジュールの属性を参照すると便利です。サブルーチン内でmy $self = shift;を使用してモジュールの属性をその変数に割り当てるように何度も言われました。これは理にかなって動作しますが、サブルーチンに引数を渡すときも、このプロセスは明らかに@ARGV配列の最初の要素を取り、$selfにも割り当てます。

誰かがシフトを使用してモジュールの属性に内部アクセスし、引数を@ARGV配列に渡す方法の説明を提供できますか?

28
Alex H Hadik

まず、サブルーチンには_@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では作成するすべてのメソッドに対して明示的に行う必要があります。

59
Nikhil

トップレベルのコードでは、shift()shift(@ARGV)の略です。 _@ARGV_にはコマンドライン引数が含まれます。

サブルーチンでは、shift()shift(@_)の短縮形です。 _@__には、サブルーチンの引数が含まれます。

_my $self = shift;_は、subの最初の引数を取得しています。メソッドを呼び出すとき、インボカント(_->_の左側)が最初のパラメーターとして渡されます。言い換えると、

_$o->method(@a)
_

と類似しています

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

その例では、_my $self = shift;_は_$o_を_$self_に割り当てます。

8
ikegami

あなたが電話した場合:

$myinstance->myMethod("my_parameter");  

以下と同じです:

myMethod($myinstance, "my_parameter");  

しかし、あなたがそうするなら:

myMethod("my_parameter");  

「my_parameter」のみが渡されます。

次に、myMethod内で常に実行する場合:

 $self = shift @_;  

オブジェクトコンテキストからmyMethod idが呼び出された場合、$ selfはオブジェクト参照になります
しかし、手順上の方法で内部の別のメソッドから呼び出された場合、「my_parameter」になります。
これに注意してください。

2
dg546gs4d65