2009-02-24 20 views
8

Actualmente estoy empezando con Perl OOP usando el paquete "Moose".¿Cómo manejo los parámetros opcionales en Moose?

El compilador se queja de que "No se puede modificar la llamada de subrutina que no es lvalue en la línea 16 de Parser.pm".

No entiendo por qué no puedo asignar un nuevo objeto. ¿Supongo que hay una forma mejor o más válida de hacer parámetros opcionales con Moose?

#!/usr/bin/perl -w 

package Parser; 

use Moose; 

require URLSpan; 

require WWW::Mechanize; 

has 'urlspan' => (is => 'rw', isa => 'URLSpan', required => 1); 
has 'mech' => (is => 'rw', isa => 'WWW::Mechanize'); 

sub BUILD { 
    my $self = shift; 
    if(!$self->mech) { 
     warn("no Mech set for " . $self->urlspan->name); 
     $self->mech = WWW::Mechanize->new(agent => 'Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.9.0.6) Gecko/2009011913 Firefox/3.0.4', 
             stack_depth => 1 
             ); #line 16 
     } 

} 
+1

No veo ninguna conexión a los parámetros opcionales. ¿Se puede ampliar al respecto? – ysth

Respuesta

13

$self->mech es una llamada a un método; realmente no puedes tratarlo como un campo en una estructura C Si desea establecerlo, debe pasarle el nuevo objeto.

 $self->mech( 
      WWW::Mechanize->new(
       agent => 'xyz', 
       stack_depth => 1 
      ) 
     ); 
5

Mientras Perl ha proporcionado la capacidad de utilizar los atributos de la forma en que está intentando durante muchos años (a través de lo que se llama valor-subs), no es algo que estaba en la primera OO Perl libera, y la gente más o menos aprendí a prescindir de eso. Especialmente desde la implementación de la validación es un poco complicado (e ineficiente).

Puede usar MooseX::Meta::Attribute::Lvalue, pero (según el documento) a costa de no tener la verificación de tipo de algunos atributos.

Recomendaría simplemente seguir con el atributo $ self-> (estilo "valor").

+0

No use ese módulo, está roto por diseño. –

+0

@Dave Rolsky: en la forma que noté, ¿o de alguna otra manera? – ysth

6

Probablemente la forma Moose preferida de hacer esto es establecer lazy_build en el atributo:

has 'mech' => (is => 'rw', isa => 'WWW::Mechanize', lazy_build => 1); 
sub _build_mech { 
    warn("no Mech set for " . $self->urlspan->name); 
    WWW::Mechanize->new(
      agent => 'Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.9.0.6)'. 
        ' Gecko/2009011913 Firefox/3.0.4', 
      stack_depth => 1 
    ); 
} 

Esto permitirá que el atributo 'Mech' para ser poblada la primera vez que se llama, a menos que se establezca lo contrario por el constructor o por el descriptor de acceso (ya que sigue siendo 'rw').

+0

¡Gracias por regresar a esta pregunta y su explicación! –

Cuestiones relacionadas