Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl 驼鹿触发呼叫器_Perl_Triggers_Moose - Fatal编程技术网

Perl 驼鹿触发呼叫器

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

有没有办法知道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 .= " - 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);