3
package JustTesting;
use strict;
use warnings;

sub new {
    my $self = {};
    bless($self, shift);
    END { $self->goodbye() };
    return $self;
}

sub goodbye {
    print "Goodbye.\n";
}

package main;
my $this = JustTesting->new();

Output:

Variable "$self" will not stay shared at ./test line 10.
Goodbye.

Apparently it works and I can suppress the warning with no warnings inside the END block. But I wonder if there is a better way how to do this.

I tried using an anonymous sub like this:

my $cleanup = sub { $self->goodbye() };
END { $cleanup->() };

and then like this:

END { sub { $self->goodbye() }->() };

But I always get the same warning.

4

5 に答える 5

22

の代わりDESTROYEND. perltoot のデストラクタに関するセクションも参照してください。

package JustTesting;
use strict;
use warnings;

sub new {
    my $self = {};
    bless($self, shift);
    return $self;
}

sub goodbye {
    print "Goodbye.\n";
}

sub DESTROY {
    my ($self) = @_;
    $self->goodbye()
};


package main;
{
    say "entering scope";
    my $this = JustTesting->new();
    say "leaving scope";
}
say "left scope";

出力:

スコープに入る
スコープを離れる
さようなら。
左スコープ
于 2009-12-16T14:01:21.663 に答える
8

将来の読者の参考のために、 daximの正解のバージョンMooseを添付しました。

use 5.012;
use warnings;

{
    package JustTesting;
    use Moose;
    use namespace::clean -except => 'meta';

    sub goodbye { say "Goodbye." }

    sub DEMOLISH {
        my ($self) = @_;
        $self->goodbye;
    }
}

{
    say "entering scope";
    my $this = JustTesting->new();
    say "leaving scope"; 
}

say "left scope";

デストラクタDEMOLISHのサブルーチンの使用に注意してください。

注意。DESTROY はまだ機能しますが、DEMOLISH は Moosey の正しい方法です。

/I3az/

于 2010-06-21T08:11:52.737 に答える
4

まず、説明についてはmy()、ネストされたサブルーチンのスコープ付き変数を参照してください。

DESTROY第二に、達成しようとしていることに応じて、またはヘルパー クラスを使用する必要があると思います。

于 2009-12-16T14:02:15.417 に答える
3

警告の理由は、見た目は似ていませんが、perl にとってENDブロックは通常の (名前付き) サブルーチンの宣言と同等であり、別のサブルーチン内で宣言された名前付きサブルーチンの動作はそうではないためです。必要に応じて、最初に呼び出されたときにブロック$selfENDにバインドさ$selfれ、プログラムの残りの期間、同じ値 (最初に作成されたインスタンス) が引き続き表示されます。最初のインスタンスはブロックによって保持される参照を持ち、プログラムが終了するまで破棄されません。その後のインスタンスでは、そのブロックがまったく呼び出されません。sub newnewENDEND

名前付きサブルーチンとは異なり、匿名サブルーチンは定義に遭遇するたびに再構築されるため、この問題はありません。そのため、閉じた変数は可能な限り遅くバインドされ、実際に必要な値がキャプチャされます。

これはかなり長い説明です。他の人が、あなたが代わりに欲しいと言っているのに、あなたが書いたコードで実際にDESTROY何が起こっているのかを知りたいと思うかもしれません。

于 2009-12-17T00:49:45.467 に答える
1

ブロックが呼び出されるまでENDに、$cleanupはすでに割り当て解除されています。変数を使用して作業を行うには、代わりにデストラクタを使用する必要があります。

perldocperlobjの「デストラクタ」を参照してください。

于 2009-12-16T18:16:23.910 に答える