3

我有一个角色和几个混合角色的类。Role 类加载所有实现类,以便任何导入 Blah 的东西都可以使用它们,而无需键入很多“使用”行。

package Blah;
use Moose::Role;

use Blah::A;
use Blah::B;
(etc...)

requires '...';
requires 'foo';
around 'foo' => sub { ... }

一个典型的 Blah 子类:

package Blah::A;
use Moose;
with 'Blah';

sub foo { ... }

__PACKAGE__->meta->make_immutable;

由于每个子类 'foo' 方法都以相同的代码位开始,因此角色也通过方法修饰符实现这些。

问题是:Moose 没有将方法修饰符应用于任何 Blah::* 类。即使我删除了类的 make_immutable 调用,也会发生这种情况。我认为角色应用完全是在运行时完成的,所以即使在 Blah 之前加载了 Blah::* 类,仍然应该应用修饰符?

我正在寻找解决方法,或另一种做事方式。目前 Blah 本质上是一个抽象基类,除了方法修饰符,这就是为什么我一开始就使用角色 - 但也许类层次结构会更好?提前致谢。

4

2 回答 2

4

你的调用顺序有点奇怪——你为什么use要从应用到 Blah::A 的角色中调用 Blah::A?

我建议拉出这些use线路并将它们移动到实际需要它们的位置(在调用者中)。先让代码工作,然后,如果你有很多use行把东西弄得乱七八糟,你可以把它们移到一个包含文件中。

但是,不,作为对您的假设的回答——角色应用程序不是在运行时完成的,而是在with遇到线路的任何时候完成的。如果您use是编译时的模块,则立即编译该文件,并with执行该行(然后强制编译该角色,然后运行)。当然,您也可以在运行时应用角色(例如,参见Moose::Util中的 apply_all_roles ),但这不是这里发生的事情。

于 2010-02-15T21:22:08.860 回答
-1

我认为您只是误解了文件包含和角色组成之间的区别。

在幕后,use语句只是调用require,然后是推断的包的import()语句,并将所有这些包装在一个BEGIN {}块中。

它不会将函数安装为具有 Class::MOP (CMOP) 的元类方法。我不确定声明的方法和导入的方法之间有什么区别,或者 CMOP 如何区分差异,但这仅因为调用add_method. 我想从 irc.perl.org/#moose 获得更多信息,但我被禁止了。希望这个例子能告诉你你需要什么,或者给你更多信息来制定一个更好的问题。

package Class;
use Moose;
use Carp qw(carp);

### You have to add the method onto the class.
Class->meta->add_method( 'carp' => \&carp );

around 'carp' => sub { warn "this won't trigger" };

package main;

my $c = Class->new;
$c->carp('foo');

如果可能的话,我会将您的那些包重写use为 Moose 友好角色,然后让当前角色使用该with语句调用新角色。角色将处理围绕其他角色提供的方法的方法修饰符。

于 2010-02-15T21:24:12.683 回答