代码之家  ›  专栏  ›  技术社区  ›  Ether

是否有任何方法可以从Moose对象中使用Moose::Exporter?

  •  3
  • Ether  · 技术社区  · 15 年前

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

    基于 example provided in the documentation ,这大概就是我想要的:

    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.
    

    顺便说一句,我也试着把出口魔法变成一个角色( with Role; extends Parent; )但同样的错误也会发生。

    1 回复  |  直到 15 年前
        1
  •  7
  •   perigrin    15 年前

    这是不受支持的,这是一个很好的理由。类或角色与sugar方法不同,在某种程度上,不同的东西应该是不同的。如果您的问题是必须“使用”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 像你在这里建议的那样引入sugar,因为一个类不是一堆sugar函数,这两者真的不应该混淆。

    更新:要同时引入两者,最干净的方法是将父对象作为应用于Moose::Object的角色重新编写。

    package Parent::Methods;
    use 5.10.0;
    use Moose::Role;
    
    sub something_special { say 'sparkles' }
    

    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
    

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