驼鹿的角色和特征有何不同?
我编写了一组在 Moose< 中实现的类和接口/a> 也使用角色。 我无法理解的是 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
I have written a set of classes and interfaces that are implemented in Moose also using roles. What I am having trouble understanding is the exact differences in both usage and implementation of Moose traits vs. roles.
The Moose documentation states:
It is important to understand that roles and traits are the same thing. A role can be used as a trait, and a trait is a role. The only thing that distinguishes the two is that a trait is packaged in a way that lets Moose resolve a short name to a class name. In other words, with a trait, the caller can refer to it by a short name like "Big", and Moose will resolve it to a class like MooseX::Embiggen::Meta::Attribute::Role::Big.
It is my understanding that traits and roles are "the same". However, when implementing a basic test of the idea using the use Moose -traits 'Foo'
syntax does not seem to do what I would expect. Surely I must be missing something here.
This first example fails with "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 -traits => 'HasTable';
__PACKAGE__->foo(); #Can't locate object method 'foo'
Compared to this one (which does work):
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是 Moose 使用术语“特质”和“角色”的唯一区别。
Moose 的文档和 API 经常使用术语“特征”作为“应用的角色”
到元类”。在您修改后的答案中,您的第一个示例将角色应用于
MyApp::User
通过-traits
的元类,第二个示例将其应用于班级。
如果将第一个示例更改为:
您将看到“
foo at [script].line 3.
”,这正是它应该做的正在做。
更新:显然我在这里并不完全正确。 特征是应用于实例的角色。
-traits
挂钩将 HasTable 应用于 MyApp::User 的元类实例。 我已经更新了相关的 Moose 文档。This is the only difference in how Moose uses the terms "Trait" and "Role".
Moose's documentation and APIs often use the term "traits" as "Roles applied
to Metaclasses". In your revised answer your first example applies the Role to
MyApp::User
's metaclass via-traits
, the second example applies it to theclass.
If you change your first example to:
You'll see "
foo at [script]. line 3.
" Which is exactly what it supposed tobe doing.
UPDATE: Apparently I'm not exactly correct here. Traits are roles applied to instances. The
-traits
hook applies HasTable to the metaclass instance for MyApp::User. I have updated the relevant Moose docs.您没有定义具有任何角色的包“x::Foo”。 直接摘自文档,我们看到
register_implementation
返回了一个实际定义的包的名称:“快捷方式”是通过Moose寻找
“Moose::Meta::Class::Trait::$来实现的Trait_name"
(在“类上下文”中调用时),而不仅仅是传回较短的名称。You don't define a package 'x::Foo' with any role. Ripped straight from the documentation, we see that
register_implementation
returns the name of an actually defined package:The "shortcut" is achieved by Moose looking for
"Moose::Meta::Class::Trait::$trait_name"
(when called in a "class context"), not just passing back a shorter name.