Подтвердить что ты не робот

Как отличаются роли и черты в лосях?

Я написал набор классов и интерфейсов, которые реализованы в 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
4b9b3361

Ответ 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" (при вызове в "контексте класса" ), а не просто передает более короткое имя.