2010-10-01 8 views
5

Sono un novizio assoluto a Moose e finora ho letto Moose e la maggior parte del Cookbook.Come posso accedere agli attributi di sola lettura degli oggetti Moose?

Ci sono alcune cose che non capisco. Ho creato il seguente pacchetto:

package MyRange; 

use Moose; 
use namespace::autoclean; 

has [ 'start', 'end' ] => (
    is  => 'ro', 
    isa  => 'Int', 
    required => 1, 
); 

__PACKAGE__->meta->make_immutable; 

1; 

Poi:

use MyRange;  
my $br = MyRange->new(
    start    => 100, 
    end     => 180 
); 

ora posso accedere ai miei campi utilizzando per esempio $br->{start}, ma posso anche modificarli (sebbene siano "di sola lettura") utilizzando ad es. $br->{start}=5000. Posso anche aggiungere nuove chiavi come $br->{xxx}=111.

Mi manca qualcosa? L'oggetto non è protetto in qualche modo? Qual è il significato di ro?

risposta

14

Quando hai detto is => 'ro' hai detto a Moose di creare accessori di sola lettura per te, ovvero un metodo di lettura. E lo chiami come

$br->start; 

o

$br->end; 

Impostazione degli attributi utilizzando questi metodi si tradurrà in un'eccezione:

$br->start(42); 

Se avessi usato is => 'rw', poi il sopra avrebbe funzionato e aggiorna il valore dell'attributo.

Quello che stai facendo è l'accesso diretto all'hash sull'oggetto, che viola l'incapsulamento e non dovrebbe mai essere necessario quando si utilizza Moose.

Il manuale di Moose, vale a dire tutti i documenti sotto lo spazio dei nomi Moose::Manual, spiegano in dettaglio. Un buon punto di partenza per domande come questa è probabilmente Moose::Manual::Attributes.

+0

+1 Grazie! Un follow-up, se posso: ho alcuni campi che non sono richiesti. Se non sono impostati, e provo ad accedere a quei valori 'undef', mi piacerebbe ricevere un errore. Devo impostare un lettore per ognuno di essi? O forse per usare qualche sub di tipo 'die' in' default'? –

+1

Si potrebbe voler creare una nuova domanda per una risposta più dettagliata su questo, ma: si dispone di un progetto in cui i valori non sono inizialmente richiesti, ma l'utente è autorizzato a compilarli in seguito utilizzando i metodi writer e deve farlo prima di chiamare alcune funzionalità che lo utilizzano? La maggior parte delle volte, dovresti probabilmente ripensare il tuo progetto lì, ma nei rari casi in cui ha senso, la mia estensione 'MooseX :: LazyRequire' potrebbe essere utile.Tutto ciò che fa è rendere obbligatorio un attributo, ma rimandare l'eccezione dal tempo di costruzione al momento in cui si accede a attr. – rafl

+0

Si noti inoltre che è possibile chiedere a Moose di generare i metodi del predicato per voi. Quelli che è possibile utilizzare per verificare esplicitamente se un valore è stato impostato per alcuni attributi tramite i metodi del costruttore o dello scrittore. Questo è particolarmente utile per gli attributi che non sono richiesti e per i quali 'undef' è un valore valido. – rafl

3

Quando si accede all'attributo con $br->{start}, si ignora l'accesso e si accede direttamente all'implementazione di Moose sottostante. Puoi farlo, ma non dovresti. Inoltre, se Moose cambia l'implementazione, il tuo codice si interromperà.

Si dovrebbe invece accedere all'attributo utilizzando il metodo di accesso:

my $start = $br->start; 

Quando si dice che l'attributo è 'RO', vuol dire che non è consentito modificare il valore dell'attributo utilizzando la funzione di accesso:

$br->start(32); 
Problemi correlati