2009-07-07 10 views
21

Napisałem zestaw klas i interfejsów, które są implementowane w Moose również za pomocą ról. To, co mam problem ze zrozumieniem, to dokładne różnice w korzystaniu i wdrażaniu cech Łosia w porównaniu z rolami.Jak Role i Cechy różnią się w Moose?

W Moose documentation stany:

ważne jest, aby zrozumieć, że role i cechy to samo. Rola może być używana jako cecha, a cecha jest rolą. Jedyną rzeczą, która odróżnia tę dwójkę, jest to, że cecha jest pakowana w sposób, który pozwala Moose rozwiązać krótkie imię i nazwisko z nazwą klasy. Innymi słowy, ze względu na cechę, wywołujący może odwoływać się do niej za pomocą krótkiej nazwy, takiej jak "Big", a Moose rozwiąże ją w klasie takiej jak MooseX :: Embiggen :: Meta :: Attribute :: Role :: Big.

Rozumiem, że cechy i role są "takie same". Jednak podczas wdrażania podstawowego testu idei przy użyciu składni use Moose -traits 'Foo' nie wydaje się, aby zrobić to, co bym oczekiwał. Na pewno tu czegoś brakuje.

To nie pierwszy przykład z "Nie można odnaleźć metody obiektowe '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' 

W porównaniu do tego, (które dział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; 
with 'MyApp::Meta::Class::Trait::HasTable'; 
__PACKAGE__->foo(); #foo 

Odpowiedz

12

Jest to jedyna różnica w tym, w jaki sposób Moose używa terminów "Cecha" i "Rola". Dokumentacja i interfejsy API Moose często używają terminu "cechy" jako "Role stosowane do Metaclasses". W swojej poprawionej odpowiedzi Twój pierwszy przykład stosuje metaklasę Rola do MyApp::User przez -traits, drugi przykład stosuje ją do klasy .

Jeśli zmienisz pierwszy przykład do:

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

Zobaczysz „foo at [script]. line 3.”, który jest dokładnie to, co ma robić.

AKTUALIZACJA: Wygląda na to, że nie jestem tutaj poprawny. Cechy to role zastosowane do instancji. Hak -traits stosuje HasTable do instancji metaclass dla MyApp :: User. Zaktualizowałem odpowiednich dokumentów Moose.

+0

Dzięki, to wyjaśnia zachowanie, które widziałem. – Danny

+1

Zaktualizowałem tekst w Przedłużanie/Przepis1.pod, aby spróbować nieco odzwierciedlić tę różnicę. Zwróć też uwagę, by pomylić rzeczy bardziej podobne do ról, nazywane są cechami w innych językach, takich jak Scala. Cechy te są zdefiniowane w niektórych artykułach, które poinformowały o pochodzeniu implementacji roli Moose, ale nie posiadają funkcji przenoszenia stanu (tj. Są to tylko metody i nie mają żadnych atrybutów). – perigrin

0

Nie zdefiniować pakiet "x :: Foo" z dowolną rolą. Zgrane prosto z documentation widzimy, że register_implementation Zwraca nazwę w rzeczywistości określonym opakowaniu:

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

z „skrót” osiąga się przez Moose szuka "Moose::Meta::Class::Trait::$trait_name" (po nazwie w „kontekście klasy”), a nie tylko przekazywanie krótszej nazwy.

+0

Proszę zobaczyć moją poprawkę do mojego pytania, próbowałem dodać więcej szczegółów. – Danny

Powiązane problemy