为什么带有方法修饰符的 Moose 角色应用程序在我的代码中不起作用?
我有一个角色和几个混合该角色的类。 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您的调用顺序有点奇怪 - 为什么您在角色中
使用
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
use
ing 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 ofuse
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 youuse
a module at compile-time, then that file is compiled immediately, and thewith
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.我认为您只是误解了文件包含和角色组合之间的区别。
在幕后,
use
语句只需调用require
,然后调用推断的 Package 的import()
语句,并将所有这些包装在BEGIN 中{}
块。它不会使用 Class::MOP (CMOP) 将函数安装为元类方法。我不确定声明的方法和导入的方法之间有什么区别,或者 CMOP 如何区分差异,但这只是因为调用了
add_method
才有效。我想从 irc.perl.org/#moose 获取更多信息,但我被禁止了。希望这个例子能告诉您您需要什么,或者为您提供更多信息来提出更好的问题。如果可能的话,我会将您
使用
的那些包重写为Moose友好的角色,然后让当前角色使用with
语句调用新角色。角色将处理其他角色提供的方法周围的方法修饰符。I think you simply misunderstand the difference between file-inclusion, and role composition.
Under the hood,
use
statements simply callrequire
and then the inferred Package'simport()
statement and wrap all of this in aBEGIN {}
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.If possible I'd rewrite those packages your
use
ing into Moose friendly Roles, then just have the current role call the new roles using thewith
statement. Roles will handle method modifiers around other role-provided methods.