【问题标题】:Moose - imported functions don't count as role methods?Moose - 导入的函数不算作角色方法?
【发布时间】:2011-10-06 02:00:31
【问题描述】:

我有一个角色声明它需要一个方法(使用requires)。 我试图通过直接在类的符号表中定义它来安装该方法。 但是,在某些情况下它有效,而在其他情况下则无效。

在下文中,WORKS 表示没有报告错误,DOESN'T WORK 表示我收到错误:'arole' requires the method 'finddepth' to be implemented by 'aclass'

package arole;

use Moose::Role;

requires 'finddepth';

package anexporter;

sub import {
  no strict 'refs';
  *{ "aclass::finddepth" } = sub {};
}

package anexporter2;
sub import {
  eval "sub aclass::finddepth {}";
}

package aclass;

use Moose;

# WORKS:
# sub finddepth { }

# WORKS:
# BEGIN { *{finddepth} = sub {} };

# DOESN'T WORK:
# use File::Find qw(finddepth);

# DOESN'T WORK:
# BEGIN { anexporter->import };

# WORKS:
# BEGIN { no strict 'refs'; *{ "aclass::finddepth" } = sub { }};

# WORKS:
# BEGIN { anexporter2->import };

with 'arole';

1;

【问题讨论】:

    标签: perl roles moose


    【解决方案1】:

    这里的问题是 Moose 非常努力地跟踪方法的来源,因此本地包中未定义的任何内容都不会意外地被视为方法。

    如果您不使用原始 glob,而是使用 Moose 元协议来注入导入,这将起作用,因为 Moose 会知道您正在尝试显式添加方法。

    package anexporter {
    
        sub import {
            aclass->meta->add_method(finddepth => sub {})
        }
    
    }
    

    但这确实意味着 CPAN 上的任何内容(例如 File::Find 的 finddepth)都需要被包装。由于通常导出不期望被称为方法,因此可能无论如何都需要发生。

    【讨论】:

    • 后续问题:Moose如何区分BEGIN { *{finddepth} = sub {} }BEGIN { anexporter->import }
    • 我不是核心专家,但我的第一个 coderef 是在当前包中定义/创建的,第二个是在外部包中创建的,本地 SV 会有一个标志说它是复制(我认为)。这是 #moose 中 rafl 或 doy 的问题。
    • @user5402,在BEGIN { *{finddepth} = sub {} },子被编译到当前包中。在BEGIN { anexporter->import } 中,子程序未在当前包中编译。您可以通过从 subs 打印 __PACKAGE__ 来查看差异。
    • @ikegami - 因为anexporter2 示例有效,在这种情况下__PACKAGE__anexporter2,而不是aclass
    【解决方案2】:

    你的角色正在寻找一个名为 finddepth 的方法;简单地从其他包中导入它并不是一种方法。我会将它包装在一个方法中,因为您的角色方法无论如何都需要调用 finddepth 作为方法,才能正确解决所有问题。

    # in package aclass
    use File::Find;
    
    sub finddepth { shift; File::Find::finddepth(@_) }
    

    这有几个优点:这并不奇怪,也不神奇,而且一切都按预期工作。

    【讨论】:

      猜你喜欢
      • 2014-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-26
      • 2013-06-13
      • 2021-05-10
      相关资源
      最近更新 更多