Perl:如何在没有警告的情况下调用END {}内的对象方法?

时间:2009-12-16 13:43:16

标签: perl perl-module

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();

输出:

  

变量“$ self”不会在./test第10行保持共享。
  再见。

显然它可以工作,我可以在END块内用no warnings来抑制警告。但我想知道是否有更好的方法 怎么做。

我尝试使用这样的匿名子:

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

然后像这样:

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

但我总是得到同样的警告。

5 个答案:

答案 0 :(得分:21)

您最有可能想要DESTROY而不是END。另请参阅the section on destructors in 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";

输出:

entering scope
leaving scope
Goodbye.
left scope

答案 1 :(得分:7)

仅为了参考未来的读者,我附上了Moose daxim版本answer的正确destructor

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";

请注意{{3}}的DEMOLISH子例程的使用。

NB。你会发现DESTROY仍然有效,但DEMOLISH是正确的Moosey方式。

/ I3az /

答案 2 :(得分:4)

首先,请参阅my() Scoped Variable in Nested Subroutines以获取解释。

其次,我认为您应该使用DESTROY或帮助程序类,具体取决于您要实现的目标。

答案 3 :(得分:3)

警告的原因是因为即使它看起来不像它,perl END块等同于常规(命名)子的声明,以及声明的命名子行为在另一个子内部不是你想要的 - $self块内的END将被绑定到$self 第一个时间内sub new调用new,它将继续在程序的剩余生命周期中看到相同的值 - 创建的第一个实例。第一个实例将具有END块所持有的引用,并且在程序结束之前不会被销毁,并且任何后续实例都不会在它们上面调用END块。

与命名的subs不同,匿名subs没有这个问题,因为它们在每次遇到它们的定义时都会重新构造,因此它们关闭的任何变量都会被尽可能晚地绑定,并且实际需要的值被捕获

这是一个很长的解释,当其他人已经告诉你,你想要的是DESTROY,但我想你可能想知道你写的代码发生了什么实际

答案 4 :(得分:1)

当调用END块时,$ cleanup已经被释放。要对变量进行任何操作,您应该使用析构函数。

请参阅perldoc perltoot处的“破坏者”。