2009-07-07 13 views
21

He escrito un conjunto de clases e interfaces que se implementan en Moose también utilizando roles. Lo que estoy teniendo problemas para comprender son las diferencias exactas tanto en el uso como en la implementación de los rasgos Moose vs. roles.¿En qué se diferencian los Roles y los Rasgos en Moose?

Los Moose documentation estados:

Es importante entender que las funciones y características son la misma cosa. Un rol puede usarse como un rasgo, y un rasgo es un rol. Lo único que distingue a los dos es que un rasgo está empaquetado de manera que permite a Moose resolver un nombre corto para un nombre de clase. En otras palabras, con un rasgo, la persona que llama puede referirse a él con un nombre corto como "Grande", y Moose lo resolverá en una clase como MooseX :: Embiggen :: Meta :: Attribute :: Role :: Big.

Tengo entendido que los rasgos y los roles son "iguales". Sin embargo, al implementar una prueba básica de la idea con la sintaxis use Moose -traits 'Foo' no parece hacer lo que esperaría. Seguramente me falta algo aquí.

Este primer ejemplo falla con "No se puede encontrar método de objeto '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' 

En comparación con éste (que funciona):

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 

Respuesta

12

Esta es la única diferencia en cómo Moose usa los términos "Rasgo" y "Papel". La documentación y las API de Moose a menudo usan el término "rasgos" como "roles aplicados a las metaclases". En su respuesta revisada, su primer ejemplo aplica la función a la metaclase MyApp::User a través del -traits, el segundo ejemplo lo aplica a la clase .

Si cambia su primer ejemplo a:

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(); 

verá "foo at [script]. line 3." ¿Qué es exactamente lo que se supone que debe estar haciendo .

ACTUALIZACIÓN: Aparentemente no estoy exactamente correcto aquí. Los rasgos son roles aplicados a las instancias. El gancho -traits aplica HasTable a la instancia de metaclase para MyApp :: User. He actualizado los documentos de Moose relevantes.

+0

Gracias, eso explica el comportamiento que estaba viendo. – Danny

+1

He actualizado el texto en Extendiendo/Recipe1.pod para tratar de reflejar esta diferencia un poco. También tenga en cuenta que para confundir las cosas más se les llama Rasgos en otros idiomas como Scala. Estos rasgos se definen en algunos documentos que informaron el origen de la implementación del rol de Moose, pero carecen de las funciones de portado del estado (es decir, son solo métodos y no tienen ningún atributo). – perigrin

0

no define una paquete 'x :: Foo' con cualquier rol. Arrancado directamente de la documentation, vemos que register_implementation Devuelve el nombre de un paquete de hecho definido:

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'); 

La "atajo" se logra mediante Moose buscando "Moose::Meta::Class::Trait::$trait_name" (cuando se llama en un "contexto de clase"), no sólo devolviendo un nombre más corto.

+0

Consulte mi revisión de mi pregunta, he intentado agregar más detalles. – Danny

Cuestiones relacionadas