Moose的角色和特质有何不同?

时间:2009-07-07 16:55:08

标签: perl moose

我编写了一组使用角色在Moose中实现的类和接口。我无法理解的是Moose特征与角色的使用和实现的确切差异。

Moose documentation州:

  

重要的是要了解角色和特征是一回事。角色可以用作特征,特征是角色。区分这两者的唯一方法是以一种让Moose将短名称解析为类名的方式打包特征。换句话说,使用特征,调用者可以通过诸如“Big”之类的短名称来引用它,并且Moose会将其解析为类似MooseX :: Embiggen :: Meta :: Attribute :: Role :: Big。 / p>

据我所知,特质和角色是“相同的”。但是,当使用use Moose -traits 'Foo'语法实现对该想法的基本测试时,似乎没有达到我期望的效果。当然,我必须在这里遗漏一些东西。

第一个示例失败,“无法找到对象方法'foo'”

package MyApp::Meta::Class::Trait::HasTable;
use Moose::Role;
sub foo { warn 'foo' }

package Moose::Meta::Class::Custom::Trait::HasTable;
sub register_implementation { 'MyApp::Meta::Class::Trait::HasTable' }

package MyApp::User;
use Moose -traits => 'HasTable';
__PACKAGE__->foo();  #Can't locate object method 'foo'

与此相比(确实有效):

package MyApp::Meta::Class::Trait::HasTable;
use Moose::Role;
sub foo { warn 'foo' }

package Moose::Meta::Class::Custom::Trait::HasTable;
sub register_implementation { 'MyApp::Meta::Class::Trait::HasTable' }

package MyApp::User;
use Moose;
with 'MyApp::Meta::Class::Trait::HasTable';
__PACKAGE__->foo();  #foo

2 个答案:

答案 0 :(得分:12)

这是Moose如何使用术语“特质”和“角色”的唯一区别。 Moose的文档和API通常使用术语“traits”作为“应用的角色” 对于元类“。在您的修订答案中,您的第一个示例将角色应用于 MyApp::User通过-traits的元类,第二个例子将其应用于 类。

如果您将第一个示例更改为:

package MyApp::Meta::Class::Trait::HasTable;
use Moose::Role;
sub foo { warn 'foo' }

package Moose::Meta::Class::Custom::Trait::HasTable;
sub register_implementation { 'MyApp::Meta::Class::Trait::HasTable' }

package MyApp::User;
use Moose -traits => 'HasTable';
__PACKAGE__->meta->foo();

你会看到“foo at [script]. line 3.”这正是它应该的样子 正在做。

更新:显然我在这里并不完全正确。特征是应用于实例的角色。 -traits挂钩将HasTable应用于MyApp :: User的元类实例。我已经更新了相关的Moose文档。

答案 1 :(得分:0)

您没有使用任何角色定义包'x :: Foo'。直接从documentation翻录,我们看到register_implementation返回实际定义的包的名称:

package MyApp::Meta::Class::Trait::HasTable;
use Moose::Role;

has table => (
  is  => 'rw',
  isa => 'Str',
);

package Moose::Meta::Class::Custom::Trait::HasTable;
sub register_implementation { 'MyApp::Meta::Class::Trait::HasTable' }

package MyApp::User;
use Moose -traits => 'HasTable';

__PACKAGE__->meta->table('User');

“快捷方式”是由Moose寻找"Moose::Meta::Class::Trait::$trait_name"(在“类上下文”中调用)而不仅仅是传回一个较短的名称来实现的。