2011-04-28 11 views
9

Łoś jest bardzo tolerancyjny domyślnie. Możesz mieć klasę o nazwie Cucumber i przekazać do konstruktora niezadeklarowany atrybut (np. wheels). Łoś nie będzie narzekał na to domyślnie. Ale może wolałbym Moose'a raczej niż zaakceptować atrybuty nierejestrowane. Jak mogę to osiągnąć? Wydaje się, że pamiętam, że przeczytałem, że jest to możliwe, ale nie mogę znaleźć miejsca, w którym to mówi w dokumentach.Jak zmusić konstruktora łosia do przejścia na niezadeklarowany atrybut?

package Gurke; 
use Moose; 
has color => is => 'rw', default => 'green'; 
no Moose; 
__PACKAGE__->meta->make_immutable; 

package main; # small test for the above package 
use strict; 
use warnings; 
use Test::More; 
use Test::Exception; 
my $gu = Gurke->new(color => 'yellow'); 
ok $gu->color, 'green'; 
if (1) { 
    my $g2 = Gurke->new(wheels => 55); 
    ok ! exists $g2->{wheels}, 'Gurke has not accepted wheels :-)'; 
    # But the caller might not be aware of such obstinate behaviour. 
    diag explain $g2; 
} 
else { 
    # This might be preferable: 
    dies_ok { Gurke->new(wheels => 55) } q(Gurken can't have wheels.); 
} 
done_testing; 

Ok, oto zaktualizowany Test ilustrujący rozwiązanie:

package Gurke; 
use Moose; 
# By default, the constructor is liberal. 
has color => is => 'rw', default => 'green'; 
no Moose; 
__PACKAGE__->meta->make_immutable; 

package Tomate; 
use Moose; 
# Have the Moose constructor die on being passed undeclared attributes: 
use MooseX::StrictConstructor; 
has color => is => 'rw', default => 'red'; 
no Moose; 
__PACKAGE__->meta->make_immutable; 

package main; # small test for the above packages 
use strict; 
use warnings; 
use Test::More; 
use Test::Exception; 

my $gu = Gurke->new(color => 'yellow'); 
ok $gu->color, 'green'; 
my $g2 = Gurke->new(wheels => 55); 
ok ! exists $g2->{wheels}, 'Gurke has not accepted wheels :-)'; 
diag 'But the caller might not be aware of such obstinate behaviour.'; 
diag explain $g2; 

diag q(Now let's see the strict constructor in action.); 
my $to = Tomate->new(color => 'blue'); 
diag explain $to; 
dies_ok { Tomate->new(wheels => 55) } q(Tomaten can't have wheels.); 

done_testing; 

Odpowiedz

15

wystarczy użyć MooseX::StrictConstructor w swojej klasie; to cecha metaclass, która już robi dokładnie to, co chcesz.

+0

Dzięki. Jak mówisz, robi dokładnie to, co chcę. Wspaniały! – Lumi

Powiązane problemy