我编写了一组使用角色在Moose中实现的类和接口。我无法理解的是Moose特征与角色的使用和实现的确切差异。
重要的是要了解角色和特征是一回事。角色可以用作特征,特征是角色。区分这两者的唯一方法是以一种让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
答案 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"
(在“类上下文”中调用)而不仅仅是传回一个较短的名称来实现的。