Perl 驼鹿触发呼叫器
有没有办法知道Moose中的触发器调用者属性 例如,以Moose::Manual::Attributes为例:Perl 驼鹿触发呼叫器,perl,triggers,moose,Perl,Triggers,Moose,有没有办法知道Moose中的触发器调用者属性 例如,以Moose::Manual::Attributes为例: has 'size' => ( is => 'rw', trigger => \&_size_set, ); sub _size_set { my ( $self, $size, $old_size ) = @_; my $msg = $self->name; if ( @_ > 2 ) { $msg
has 'size' => (
is => 'rw',
trigger => \&_size_set,
);
sub _size_set {
my ( $self, $size, $old_size ) = @_;
my $msg = $self->name;
if ( @_ > 2 ) {
$msg .= " - old size was $old_size";
}
$msg .= " - size is now $size";
warn $msg;
}
在\u set\u size中是否可能知道属性size调用了它,而不需要显式指定调用方属性的名称
编辑:按注释更新。创建添加一个参数的包装可能更简单:
sub make_trigger {
my ($name, $sub) = @_;
return sub {
my $self = shift;
$self->$sub($name, @_);
};
}
has 'size' => (
is => 'rw',
trigger => make_trigger(size => \&_size_set),
);
sub _size_set {
my ( $self, $name, $size, $old_size ) = @_;
...
}
正确的方法是使用某种属性特征;传递触发器所属属性的名称或(最好)元类实例的对象。我们甚至可以创建一个特性,允许类的元类被询问是否在属性触发器中,如果是,是哪一个。(这将是透明的,不会打破任何人对触发器工作方式的期望。)
最简单的就是像另一个例子中所示的那样使用触发器。这里是@RsrchBoy所说的“正确的方法” 您会注意到“foo”和“bar”属性共享一个触发器,但触发器能够区分这两个属性
驼鹿:出口商有一些糖可以让它看起来不那么难看。有一天,我可能会尝试将其转换为CPAN模块。我直接在触发器函数中的代码中做了类似的操作:
trigger=>sub{$\u0]->\u set\u size('attribute\u caller\u function',@},
…问题是我想避免显式指定调用方属性的名称。有没有可能给我一个正确方法的示例?我如何创建一个特性,允许类的元类被询问是否在属性触发器中?请参阅我对问题的回答,以获得“正确方式”的示例:-)非常感谢!工作完美!这是现在。
use v5.14;
use strict;
use warnings;
BEGIN {
package MooseX::WhatTheTrig::Trait::Attribute
{
use Moose::Role;
use Scope::Guard qw(guard);
after _process_trigger_option => sub
{
my $class = shift;
my ($name, $opts) = @_;
return unless exists $opts->{trigger};
my $orig = delete $opts->{trigger};
$opts->{trigger} = sub
{
my $self = shift;
my $guard = guard {
$self->meta->_set_triggered_attribute(undef);
};
$self->meta->_set_triggered_attribute($name);
$self->$orig(@_);
};
}
}
package MooseX::WhatTheTrig::Trait::Class
{
use Moose::Role;
has triggered_attribute => (
is => 'ro',
writer => '_set_triggered_attribute',
);
}
}
package Example
{
use Moose -traits => ['MooseX::WhatTheTrig::Trait::Class'];
has [qw(foo bar)] => (
traits => ['MooseX::WhatTheTrig::Trait::Attribute'],
is => 'rw',
trigger => sub {
my ($self, $new, $old) = @_;
$_ //= 'undef' for $old, $new;
my $attr = $self->meta->triggered_attribute;
say "Changed $attr for $self from $old to $new!";
}
);
}
my $obj = Example->new(foo => 1, bar => 2);
$obj->foo(3);
$obj->bar(4);