21

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

Moose 文档指出:

重要的是要了解角色和特征是一回事。角色可以用作特质,特质就是角色。区分这两者的唯一一点是,一个 trait 以一种允许 Moose 将短名称解析为类名的方式打包。换句话说,对于一个 trait,调用者可以通过一个短名称来引用它,比如“Big”,Moose 会将它解析为一个类,比如 MooseX::Embiggen::Meta::Attribute::Role::Big。

我的理解是特征和角色是“相同的”。但是,当使用语法对想法进行基本测试时,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
4

2 回答 2

12

这是 Moose 使用术语“特征”和“角色”的唯一区别。Moose 的文档和 API 经常使用术语“特征”作为“应用于元类的角色”。在您修改后的答案中,您的第一个示例将 Role 应用于 MyApp::User的元类 via -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 文档。

于 2009-07-08T04:24:26.903 回答
0

您没有定义具有任何角色的包 'x::Foo'。直接从文档中提取,我们看到它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"(在“类上下文”中调用时)实现的,而不仅仅是传回一个较短的名称。

于 2009-07-07T19:01:43.350 回答