2009-07-07 6 views
21

Ich habe eine Reihe von Klassen und Schnittstellen geschrieben, die in Moose auch mit Rollen implementiert sind. Was ich nicht verstehen kann, sind die genauen Unterschiede bei der Verwendung und Implementierung von Moose-Merkmalen im Vergleich zu Rollen.Wie unterscheiden sich Rollen und Eigenschaften in Elch?

Die Moose documentation Staaten:

Es ist wichtig zu verstehen, dass die Rollen und Eigenschaften die gleiche Sache sind. Eine Rolle kann als Merkmal verwendet werden, und eine Eigenschaft ist eine Rolle. Das einzige, was die beiden unterscheidet, ist, dass ein Merkmal so verpackt ist, dass Moose einen kurzen Namen in einen Klassennamen auflöst. Mit anderen Worten, mit einem Merkmal kann der Aufrufer darauf durch einen kurzen Namen wie "Big" verweisen, und Moose wird es in eine Klasse wie MooseX :: Embiggen :: Meta :: Attribute :: Role :: Big auflösen.

Es ist mein Verständnis, dass Merkmale und Rollen "die gleichen" sind. Allerdings, wenn die Implementierung eines grundlegenden Tests der Idee mit der use Moose -traits 'Foo' Syntax scheint nicht zu tun, was ich erwarten würde. Sicherlich muss ich hier etwas vermissen.

Dieses erste Beispiel schlägt mit

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' 

Im Vergleich zu diesem (die Arbeit der Fall ist) "Can not Objektmethode 'foo' finden":

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 

Antwort

12

Dies ist der einzige Unterschied, wie Moose die Begriffe "Merkmal" und "Rolle" verwendet. Die Dokumentation und die APIs von Moose verwenden häufig den Begriff "Merkmale" als "Angewandte Rollen an Metaklassen". In Ihrer überarbeiteten Antwort wendet Ihr erstes Beispiel die Rolle auf die Metaklasse MyApp::User über -traits an, das zweite Beispiel wendet sie auf die Klasse an.

Wenn Sie Ihr erstes Beispiel ändern:

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

werde You „ foo at [script]. line 3.“ sehen, welche genau das, was es zu tun soll.

UPDATE: Anscheinend bin ich hier nicht genau richtig. Eigenschaften sind Rollen, die auf Instanzen angewendet werden. Der -traits -Hook wendet HasTable auf die Metaklasseninstanz für MyApp :: User an. Ich habe die relevanten Elchdokumente aktualisiert.

+0

Danke, das erklärt das Verhalten, das ich sah. – Danny

+1

Ich habe den Text in Extending/Recipe1.pod aktualisiert, um zu versuchen, diesen Unterschied ein wenig widerzuspiegeln. Beachten Sie auch, Dinge mehr zu verwirren. Rollenähnliche Dinge werden in anderen Sprachen wie Scala als Traits bezeichnet. Diese Merkmale sind in einigen Papieren definiert, die den Ursprung von Mooses Rollenimplementierung beschrieben haben, aber nicht den Status, der Merkmale enthält (dh sie sind nur Methoden und haben keine Attribute). – perigrin

0

Sie definieren nicht ein Paket 'x :: Foo' mit jeder Rolle. Ripped direkt aus dem documentation sehen wir, dass register_implementation gibt den Namen eines tatsächlich definiert Paket:

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

Die „Abkürzung“ wird von Moose erzielt für "Moose::Meta::Class::Trait::$trait_name" suchen (wenn sie in einem „Klassenkontext“ genannt), nicht nur einen kürzeren Namen zurückgeben.

+0

Bitte beachten Sie meine Revision zu meiner Frage, ich habe versucht, mehr Details hinzuzufügen. – Danny

Verwandte Themen