Moose - 导入的函数不算作角色方法?

发布于 2024-12-03 19:37:11 字数 796 浏览 1 评论 0原文

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

在下面,WORKS 意味着没有报告错误,DOESN'T WORK 意味着我收到错误:'arole' 要求方法 'finddepth' 由 '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;

I have a role that declares that it requires a method (with requires).
I'm trying to install the method by directly defining it in the class's symbol table.
However, in some cases it works and in others it doesn't.

In the following, WORKS means no errors are reported, DOESN'T WORK means I get the error: '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;

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

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

发布评论

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

评论(2

↙厌世 2024-12-10 19:37:11

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

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

package anexporter {

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

}

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

The problem here is that Moose tries very hard to track where methods are coming from so that anything not defined in the local package isn't accidentally treated as a method.

If instead of using the raw glob you were to use the Moose metaprotocol to inject the import this would work, because Moose would then know you were trying to explicitly add a method.

package anexporter {

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

}

However this does mean that anything on CPAN (like File::Find's finddepth) would need to be wrapped. Which since typically exports aren't expecting to be called as methods, would probably need to happen anyway.

生死何惧 2024-12-10 19:37:11

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

# in package aclass
use File::Find;

sub finddepth { shift; File::Find::finddepth(@_) }

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

Your role is looking for a method named finddepth; simply importing it from some other package does not a method make. I'd wrap it in a method, as your role methods would need to call finddepth as a method anyways, to have everything resolve properly.

# in package aclass
use File::Find;

sub finddepth { shift; File::Find::finddepth(@_) }

This has a couple advbantages: it's not surprising, it's not magical, and everything works as expected.

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