4

我有这个代码:

package Foo;
use Moo;

has attr => ( is => "rw", trigger => 1 );

sub _trigger_attr 
    { print "trigger! value:". shift->attr ."\n" }


package main;
use Foo;

my $foo = Foo->new( attr => 1 );
$foo->attr( 2 );

它返回:

$ perl test.pl
trigger! value:1
trigger! value:2

这是 Moo 中触发器的默认记录行为。

如果属性是通过构造函数设置的,如何禁用触发器执行?

当然我可以这样做:

package Foo;
use Moo;

has attr        => ( is => "rw", trigger => 1 );
has useTriggers => ( is => "rw", default => 0 );

sub _trigger_attr 
{ 
    my $self = shift;
    print "trigger! value:". $self->attr ."\n" if $self->useTriggers 
}

package main;
use Foo;

my $foo = Foo->new( attr => 1 );
$foo->useTriggers( 1 );
$foo->attr( 2 );

并得到:

$ perl testt.pl
trigger! value:2

所以它有效,但是......感觉不对;)。

4

2 回答 2

8

我不太了解Moo,但是Moose您可以在构造函数之后实现自己的代码。如果你能做这样的事情,Moo它会给你想要的效果。

sub BUILD {
    my $self = shift;

    # Sets "useTriggers" AFTER the object is already constructed.
    $self->useTriggers(1);
};

这将导致useTriggers在构造之后设置,因此触发器将在构造对象之后激活,但在构造之前不会。

所以你应该能够写:

my $foo->new(attr => 1);
$foo->attr(2);

并获得相同的输出。

于 2018-02-05T14:33:05.320 回答
7
package Foo;
use Moo;

has attr => ( accessor => '_attr' );

sub attr { 
    my $self = shift;
    my $rv = $self->_attr(@_);
    print "trigger! value: ", $rv if @_;
    return $rv;
}


package main;
use Foo;

my $foo = Foo->new( attr => 1 );
$foo->attr( 2 );
于 2018-02-05T14:42:22.380 回答