Как отличаются роли и черты в лосях?
Я написал набор классов и интерфейсов, которые реализованы в Moose, также используя роли. То, что мне трудно понять, - это точные различия как в использовании, так и в реализации признаков лося по сравнению с ролями.
Документация Moose гласит:
Важно понимать, что роли и черты - одно и то же. Роль может использоваться как признак, и черта - это роль. Единственное, что отличает их, - это то, что черта упакована таким образом, что позволяет 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
Ответы
Ответ 1
Это единственная разница в том, как Moose использует термины "Trait" и "Role".
Документация Moose и API часто используют термин "признаки" как "Используемые роли
к метаклассам ". В вашем пересмотренном ответе ваш первый пример применяет роль
MyApp::User
metaclass через -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.
Ответ 2
Вы не определяете пакет '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"
(при вызове в "контексте класса" ), а не просто передает более короткое имя.