有什么方法可以在 Moose 对象中使用 Moose::Exporter 吗?

发布于 2024-08-13 07:35:05 字数 1335 浏览 4 评论 0原文

我正在寻找一种在父 Moose 类中设置一些辅助方法的方法,而不是一个独立的实用程序类。如果可能的话,这将是一种向模块添加 Moose 糖的更透明的方式,因为它不需要明确要求任何辅助模块(因为一切都将通过 extends 声明来实现)。

基于文档中提供的示例,这大致就是我的情况追求:

package Parent;

use Moose;

Moose::Exporter->setup_import_methods(
    with_meta => [ 'has_rw' ],
    as_is     => [ 'thing' ],
    also      => 'Moose',
);

sub has_rw {
    my ( $meta, $name, %options ) = @_;
    $meta->add_attribute(
        $name,
        is => 'rw',
        %options,
    );
}

# then later ...
package Child;

use Moose;
extends 'Parent';

has 'name';
has_rw 'size';
thing;

但这不起作用:

perl -I. -MChild -wle'$obj = Child->new(size => 1); print $obj->size'
String found where operator expected at Child.pm line 10, near "has_rw 'size'"
        (Do you need to predeclare has_rw?)
syntax error at Child.pm line 10, near "has_rw 'size'"
Bareword "thing" not allowed while "strict subs" in use at Child.pm line 12.
Compilation failed in require.
BEGIN failed--compilation aborted.

PS。我还尝试将导出魔法移至角色(with Role; 而不是 extends Parent;),但出现了相同的错误。

I'm looking for a way to set up some helper methods from within a parent Moose class, rather than a standalone utility class. If it is possible, it would be a more transparent way of adding Moose sugar to modules, as it does not require explicitly requiring any helper modules (as everything would come via the extends declaration).

Based on the example provided in the documentation, this is roughly what I am going for:

package Parent;

use Moose;

Moose::Exporter->setup_import_methods(
    with_meta => [ 'has_rw' ],
    as_is     => [ 'thing' ],
    also      => 'Moose',
);

sub has_rw {
    my ( $meta, $name, %options ) = @_;
    $meta->add_attribute(
        $name,
        is => 'rw',
        %options,
    );
}

# then later ...
package Child;

use Moose;
extends 'Parent';

has 'name';
has_rw 'size';
thing;

However this does not work:

perl -I. -MChild -wle'$obj = Child->new(size => 1); print $obj->size'
String found where operator expected at Child.pm line 10, near "has_rw 'size'"
        (Do you need to predeclare has_rw?)
syntax error at Child.pm line 10, near "has_rw 'size'"
Bareword "thing" not allowed while "strict subs" in use at Child.pm line 12.
Compilation failed in require.
BEGIN failed--compilation aborted.

PS. I've also tried moving the export magic into a role (with Role; rather than extends Parent;) but the same errors occur.

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

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

发布评论

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

评论(1

始终不够爱げ你 2024-08-20 07:35:05

这是不支持的,这是有充分理由的。类或角色与糖方法不同,并且在某种程度上不同的东西应该是不同的。如果您的问题是必须“使用”Moose + 自定义糖包,那么您可以通过简单地让您的自定义糖包导出 Moose 来解决这个问题,从您的示例中窃取:

package MySugar;
use strict;
use Moose::Exporter;

Moose::Exporter->setup_import_methods(
    with_meta => [ 'has_rw' ],
    as_is     => [ 'thing' ],
    also      => 'Moose',
);

sub has_rw {
    my ( $meta, $name, %options ) = @_;
    $meta->add_attribute(
        $name,
        is => 'rw',
        %options,
    );
}

然后您只需说:

package MyApp;
use MySugar; # imports everything from Moose + has_rw and thing    
extends(Parent);

has_rw 'name';
has 'size';
thing;

这就是 MooseX 的方式: :POE 以及其他几个包都可以工作。我反对像您在这里建议的那样使用 extends 引入糖,因为类不是糖函数的捆绑,并且两者真的不应该混淆。

更新:要同时引入两者,最简洁的方法是将 Parent 重新设计为应用于 Moose::Object 的角色。

package Parent::Methods;
use 5.10.0;
use Moose::Role;

sub something_special { say 'sparkles' }

然后我们只需将 MySugar 中对 Moose::Exporter 的调用更改为如下所示。

Moose::Exporter->setup_import_methods(
    apply_base_class_roles => 'Parent::Methods',
    with_meta              => ['has_rw'],
    as_is                  => ['thing'],
    also                   => 'Moose',
);

现在您可以简单地说

package MyApp;
use MySugar; 

has_rw 'name';
has 'size';
thing;

package main;
MyApp->new->something_special; # prints sparkles

“我相信这是您想要的最终细节”。

This isn't supported, and there is a good reason why. A Class or a Role are not the same as sugar methods, and at some level different things should be different. If your problem is having to "use" Moose + A Custom Sugar package then you can solve that by simply having your custom sugar package export Moose as well, stealing from your example:

package MySugar;
use strict;
use Moose::Exporter;

Moose::Exporter->setup_import_methods(
    with_meta => [ 'has_rw' ],
    as_is     => [ 'thing' ],
    also      => 'Moose',
);

sub has_rw {
    my ( $meta, $name, %options ) = @_;
    $meta->add_attribute(
        $name,
        is => 'rw',
        %options,
    );
}

Then you simply say:

package MyApp;
use MySugar; # imports everything from Moose + has_rw and thing    
extends(Parent);

has_rw 'name';
has 'size';
thing;

This is how MooseX::POE works, as well as several other packages. I for one would argue against having extends bring in the sugar like you're suggesting here because a Class is not a bundle of sugar functions, and the two really should never be confused.

UPDATE: To bring in both at once the cleanest approach is to rework Parent as a role that is applied to Moose::Object.

package Parent::Methods;
use 5.10.0;
use Moose::Role;

sub something_special { say 'sparkles' }

Then we simply change the call to Moose::Exporter in MySugar to look like

Moose::Exporter->setup_import_methods(
    apply_base_class_roles => 'Parent::Methods',
    with_meta              => ['has_rw'],
    as_is                  => ['thing'],
    also                   => 'Moose',
);

Now you can simply say

package MyApp;
use MySugar; 

has_rw 'name';
has 'size';
thing;

package main;
MyApp->new->something_special; # prints sparkles

Which is I believe the final detail you were wanting.

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