2010-11-19 10 views
6

Tengo un montón de funciones perezosas en un objeto Moose.¿Cómo puedo hacer que se creen todas las características perezosas de Moose?

Algunos de los constructores requieren algo de tiempo para terminar.

Me gustaría anotar todos los constructores (el objeto "bomplete"). ¿Puedo crear todas las características perezosas a la vez, o debo llamar a cada característica de forma manual para que se ejecute el constructor?

+1

¿No deberías estar usando 'default' para eso? Pensé que el objetivo de 'vago' era posponer la creación del valor del atributo hasta el primer uso. Si necesita que todos los atributos se configuren en la construcción del objeto, 'default' parece más útil. O bien, puede proporcionar su propio método 'BUILD'. –

+0

Este es un modismo bastante común y hay algunas razones decentes para ello. – hobbs

+0

Básicamente, puede hacer todo el trabajo en 'BUILD' en su lugar, pero es mejor tener un método por atributo. Y si va a tener un método por atributo para calcular el valor, entonces bien podría ser un generador. Pero si un constructor va a acceder a otros atributos, entonces el atributo creado debe ser flojo para asegurarse de que se haya inicializado. Y no hay una opción de atributo "vago, sino solo * un poco * holgazán" :) – hobbs

Respuesta

6

Si desea tener atributos "flojos" con constructores, pero asegúrese de que sus valores se construyan antes de new, lo habitual es llamar a los descriptores de acceso en BUILD.

sub BUILD { 
    my ($self) = @_; 

    $self->foo; 
    $self->bar; 
} 

es suficiente para hacer el trabajo, pero es probable que sea mejor añadir un comentario explicando así el código aparentemente inútil a alguien que no conoce el idioma.

3

Quizás podría usar la metaclase para obtener la lista de atributos 'perezosos'. Por ejemplo:

package Test; 

use Moose; 


has ['attr1', 'attr2'] => (is => 'rw', lazy_build => 1); 
has ['attr3', 'attr4'] => (is => 'rw',); 

sub BUILD { 
    my $self = shift; 


    my $meta = $self->meta; 

     foreach my $attribute_name (sort $meta->get_attribute_list) { 

     my $attribute = $meta->get_attribute($attribute_name); 

     if ($attribute->has_builder) { 
      my $code = $self->can($attribute_name); 
      $self->$code; 

     } 
    } 

} 


    sub _build_attr1 { 1 } 
    sub _build_attr2 { 1 } 
2

He tenido este requisito exacto varias veces en el pasado, y hoy en día que en realidad tenía que hacerlo desde la metaclase, que significaba que no pellizcar BUILD permitido. De todas formas me sentí que sería bueno compartir ya que básicamente hace exactamente lo éter mencionado:

'Esto permitiría marcar atributos "esto es vago, porque depende en otros valores de atributos para ser construido, pero quiero . que sea empujado antes de acabados de construcción "'

sin embargo, derp derp no tengo ni idea de cómo hacer un módulo CPAN así que aquí tiene algunos códigos: https://gist.github.com/TiMBuS/5787018

Poner lo anterior en Late.pm y entonces puedes usar i t gusta así:

package Thing; 
use Moose; 
use Late; 

has 'foo' => (
    is  => 'ro', 
    default => sub {print "setting foo to 10\n"; 10}, 
); 

has 'bar' => (
    is  => 'ro', 
    default => sub {print 'late bar being set to ', $_[0]->foo*2, "\n"; $_[0]->foo*2}, 
    late => 1, 
); 

#If you want.. 
__PACKAGE__->meta->make_immutable; 
1; 


package main; 

Thing->new(); 
#`bar` will be initialized to 20 right now, and always after `foo`. 
#You can even set `foo` to 'lazy' or 'late' and it will still work. 
Cuestiones relacionadas