4

我想将 Moose 'before' 方法修饰符应用于我班级中的许多方法。我想在角色中提供修饰符方法。我可以这样做:

package MyApp::Role;

use Moose::Role

before [qw(foo bar)] => sub {
    ...
};

package MyApp;

use Moose;
with (MyApp::Role);

sub foo { ... }

sub bar { ... }

sub baz { ... } # this method is unaffected

但是,必须在角色中维护相关方法列表会将其与消费类联系起来,这似乎是错误的。我想用更聪明的方式来做,比如方法属性:

package MyApp;

use Moose;
with (MyApp::Role);

sub foo :SomeFlag { ... }

sub bar :SomeFlag { ... }

sub baz { ... } # this method is unaffected

我不熟悉如何识别方法属性或如何动态地将方法修饰符应用于它们。

或者,也许有更好的方法来做到这一点?

4

1 回答 1

5

让我们使用Attribute::Handlers它——一种相当理智的使用属性的方法。我们必须在本身具有属性的基类中定义一个函数:ATTR(CODE)。这需要一些参数:

  1. 子(或其他变量)来自的包。
  2. 一个 globref 或字符串ANON
  3. 对值的引用(此处:coderef)。
  4. 属性的名称。
  5. 属性的可选数据。
  6. 调用属性的(编译)阶段。
  7. 声明 sub 的文件名。
  8. 声明 sub 的行号。

所以我们可以做的是编写一个应用程序的处理程序before

use strict; use warnings; use feature 'say';

BEGIN {
    package MyRole;
    use Moose::Role;
    use Attribute::Handlers;

    sub SomeFlag :ATTR(CODE) {
        my ($package, $globref, $code, $attr, $data, $phase, $filename, $line) = @_;

        ref($globref) eq 'GLOB'
            or die "Only global subroutines can be decorated with :SomeFlag"
                    . " at $filename line $line.\n";

        # use the MOP to install the method modifier
        $package->meta->add_before_method_modifier(
            *$globref{NAME} => sub {
                warn "Just about to call a flagged sub!";
            },
        );
    }
}

BEGIN {
    package MyApp;
    use Moose;
    # important: SomeFlag must be available before the attrs are handled (CHECK phase)
    BEGIN { with 'MyRole' };

    sub foo :SomeFlag { say "Hi from foo sub!" }
    sub bar :SomeFlag { say "Hi from bar sub!" }
    sub baz           { say "Hi from baz sub!" }
}

package main;

my $o = MyApp->new;
$o->$_ for qw/foo bar baz/;

我将所有这些都塞进了一个文件中,但这显然不是必需的(只需添加所需use的 s)。

输出:

Just about to call a flagged sub! at so.pl line 16.
Hi from foo sub!
Just about to call a flagged sub! at so.pl line 16.
Hi from bar sub!
Hi from baz sub!
于 2013-08-30T10:37:38.457 回答