为什么带有方法修饰符的 Moose 角色应用程序在我的代码中不起作用?

发布于 2024-08-22 00:58:55 字数 659 浏览 13 评论 0原文

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

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 本质上是一个抽象基类,这就是我一开始使用角色的原因 - 但也许类层次结构会更好?提前致谢。

I have a Role and several classes that mix-in the role. The Role class loads all of the implementing classes so that anything that imports Blah can use them without typing a lot of 'use' lines.

package Blah;
use Moose::Role;

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

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

A typical Blah subclass:

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

sub foo { ... }

__PACKAGE__->meta->make_immutable;

Since every subclass 'foo' method starts with the same bits of code, the role also implements these via a method modifier.

Problem is: Moose doesn't apply the method modifier to any of the Blah::* classes. This happens even if I remove the make_immutable call for the classes. I thought role application was done entirely at runtime, and so even though the Blah::* classes are loaded before Blah, the modifier should still be applied?

I'm looking for a fix, or an alternate way of doing things. At the moment Blah is essentially an abstract base class except for the method modifier, which is why I used roles to begin with - but maybe a class hierarchy would be better? Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

你不是我要的菜∠ 2024-08-29 00:58:55

您的调用顺序有点奇怪 - 为什么您在角色中使用Blah::A,然后将其应用于Blah::A?

我建议拉出这些 use 行并将它们移动到实际需要的位置(在调用者中)。首先让代码正常工作,然后,如果您有很多 use 行,到处都乱七八糟,您可以将它们移到 Includes 文件中。

但不,回答你的假设——角色应用不是在运行时完成的,而是在任何时候遇到with行时完成的。如果您在编译时使用模块,那么该文件将立即编译,并执行with行(然后强制编译角色,然后它是跑步)。当然,您也可以在运行时应用角色(例如,请参阅 Moose::Util< 中的 apply_all_roles /a>),但这不是这里发生的情况。

Your call order is a little odd -- why are you useing Blah::A from within the role that is then applied to Blah::A?

I would suggest pulling out these use lines and moving them to where they are actually needed (in the caller(s)). Get the code working first, and after that, if you have lots of use lines cluttering things up everywhere, you could move them off into an Includes file.

But no, in answer to your assumption -- role application is not done at runtime, but at whatever time the with line is encountered. If you use a module at compile-time, then that file is compiled immediately, and the with line executed (which then forces the role to be compiled, and then it is run). You can of course apply a role at runtime as well (e.g. see apply_all_roles in Moose::Util), but that is not what is happening here.

终陌 2024-08-29 00:58:55

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

在幕后,use 语句只需调用 require,然后调用推断的 Package 的 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');

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

I think you simply misunderstand the difference between file-inclusion, and role composition.

Under the hood, use statements simply call require and then the inferred Package's import() statement and wrap all of this in a BEGIN {} block.

It doesn't install the functions as meta-class methods with Class::MOP (CMOP). I'm not sure what the difference is between a declared method and an imported one, or how CMOP tells the difference but this works only because of the call to add_method. I'd ask for more information from irc.perl.org/#moose, but I'm banned. Hopefully this example will tell you what you need, or give you more information to formulate a better question.

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');

If possible I'd rewrite those packages your useing into Moose friendly Roles, then just have the current role call the new roles using the with statement. Roles will handle method modifiers around other role-provided methods.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文