3

我正在寻找一种从父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'
在 Child.pm 第 10 行,“has_rw 'size'”附近的操作员预期的位置找到字符串
        (是否需要预先声明 has_rw?)
Child.pm 第 10 行的语法错误,靠近“has_rw 'size'”
在 Child.pm 第 12 行使用“strict subs”时不允许使用裸词“thing”。
编译失败。
BEGIN 失败——编译中止。

PS。我也尝试将导出魔法移动到一个角色(with Role;而不是extends Parent;)中,但是会发生同样的错误。

4

1 回答 1

7

这不受支持,这是有充分理由的。类或角色与糖方法不同,在某种程度上不同的东西应该是不同的。如果您的问题是必须“使用” Moose + A Custom Sugar 包,那么您可以通过简单地让您的自定义糖包导出 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

我相信你想要的最后一个细节。

于 2009-12-02T06:17:14.953 回答