Perl 将角色组合到Moose类中不起作用
你好 我有一个角色,我正忙着在一个名为Authable的Moose类中定义它,该类基本上被组合成任何将来可能需要某种形式的身份验证的类;这是一个相当简单的角色,全部内容如下:Perl 将角色组合到Moose类中不起作用,perl,oop,moose,Perl,Oop,Moose,你好 我有一个角色,我正忙着在一个名为Authable的Moose类中定义它,该类基本上被组合成任何将来可能需要某种形式的身份验证的类;这是一个相当简单的角色,全部内容如下: package Trello::API::Roles::Authable; use Moose::Role; #authentication information has key => ( is => "rw", isa => "Str", ); has token => (
package Trello::API::Roles::Authable;
use Moose::Role;
#authentication information
has key => (
is => "rw",
isa => "Str",
);
has token => (
is => "rw",
isa => "Str",
);
1;
无论出于何种原因,当我试图使用多个不同的语句将其组合到一个类中时,例如。,
使用“Trello::API::Roles::Authable”;
或
使用“Roles::Authable”
我始终收到相同的错误消息:您只能使用角色,角色::Authable不是驼鹿角色。
知道为什么会这样吗
编辑
只是一个旁注,我检查了Moose::Role的实际源代码,看到了以下内容:
unless ($meta && $meta->isa('Moose::Meta::Role') ) {
require Moose;
Moose->throw_error( "You can only consume roles, "
. $role->[0]
. " is not a Moose role" );
}
这似乎是发生错误的地方,因此出于某种原因,我正在实现的角色似乎没有声明它是元类中的角色。虽然我可能弄错了!任何帮助都将不胜感激
另一个方便的编辑
额外好处:调用with例程的代码上下文
package Trello::API::Resource;
use Moose;
use URI::Escape;
use LWP::UserAgent;
with 'Roles::Authable';
当我这样做的时候,它很聪明地知道尝试和使用Roles/Authable.pm,但无论出于什么原因,它都无法正常工作 首先,我必须同意Piers的观点,从技术上讲,你真的应该用“Trello::API::Roles::Authable”将其称为
所以,你要求的是一些我没有发现能在基本Moose中实现的东西。
我以前使用过通用名称空间池的思想。它们是一种通用名称空间,您可以向其提供
半匿名服务——没有固定名称空间的锁定。我用Moose(实际上是MOP
)支持完善了名称空间池的基本概念
在Wild West的Perl时代,您所要做的就是为另一个符号指定一个隐藏,如下所示:
{ no strict 'refs';
*{$short_pkg_name.'::'} = \*{$full_pkg_name.'::'};
};
而且,这两个包是完全一样的东西
但现在,我们更多地使用词汇来保护数据。由于Class::MOP小心翼翼地在词法散列中保护其元对象,因此必须添加其他内容:
Class::MOP::store_metaclass_by_name(
$short_pkg_name
, Class::MOP::get_metaclass_by_name( $full_pkg_name )
);
现在,对于Perl和MOP来说,它们是完全相同的东西
因此,您可以创建只作为其他包的命名空间存储库的包
--现在有了MOP
支持
并且知道它将从“角色”的名称空间中可用。在我的例子中,我只是意外地将我的角色命名为“Test”,但我的系统上已经安装了一个名为“Test”的模块,因此Moose认为我想使用该模块,而不是我创建的新Moose角色。一旦我将role重命名为“Testable”,一切都很好。你所说的“多个不同的语句”是什么意思?是使用“Trello::API::Roles::Authable”还是使用“Roles::Authable”代码>?因为你似乎没有后一个名字的角色,我的意思是我尝试了多种不同的变体;此时,尝试使用角色的文件是Trello::API::Resource,因此它似乎将Roles::Authable识别为Trello::API::Roles::Authable,并尝试使用该模块。此时,它无法识别模块的位置,因为我没有将它们放入实际的模块目录结构中;我可以随时修改@INC,但现在我只是好奇为什么不能这样使用这个角色。您是在多个文件中声明代码,还是只在一个文件中声明代码?您的类是按什么顺序定义的?您确实应该使用“Trello::API::Roles::Authable”
来执行,并且为了实现这一点,您应该已经使用require
d Trello::API::Roles::Authable,或者T::A::R::Authable应该在lib/Trello/API/Roles/Authable.pm
中定义。在这种情况下,Moose不会对包名施展魔法;它不知道当你用“Roles::Authable”
说时,你真正的意思是用“Trello::API::Roles::Authable”
说,怎么可能呢?所以,要么把你的软件包放在适当命名的文件中,以便Moose能够找到它们,要么require
在尝试编写任何东西之前,需要任何奇怪的文件。我非常感谢。在我意识到这个角色起作用后,我最终使用了这个角色的完全限定名,所以,问题解决了,但您的解释非常深入,为实现我的目标提供了一个良好的起点,所以非常感谢您的努力。
package Namespace::Pool;
use strict;
use warnings;
use Params::Util qw<_POSINT>;
sub import {
shift; # It's just me.
my $full_pkg_name = caller();
Carp::croak( "'$full_pkg_name' is short enough!" )
unless my $pool_name
= shift // [ split /::/, $full_pkg_name ]->[-2]
;
Carp::croak( "'::$pool_name\::' not found in '$full_pkg_name'" )
unless ( _POSINT( my $pos = rindex( $full_pkg_name, "::$pool_name\::" ))
or my $is_short = _POSINT( index( $pool_name, '::' ))
);
my $short_pkg_name
= $is_short ? $poll_name
: substr( $full_pkg_name, $pos + 2 )
;
{ no strict 'refs';
if ( %{$short_pkg_name.'::'} ) {
Carp::croak( "You have already defined $short_pkg_name!" );
}
*{$short_pkg_name.'::'} = \*{$full_pkg_name.'::'};
};
if ( my $meta = Class::MOP::get_metaclass_by_name( $full_pkg_name )) {
Class::MOP::store_metaclass_by_name( $short_pkg_name, $meta );
}
return;
}
package Trello::API::Roles::Authable;
use strict;
use warnings;
use Moose::Role;
use Namespace::Pool 'Roles';
...