2009-02-24 33 views
8

Tôi hiện đang bắt đầu với Perl OOP bằng gói "Moose".Làm cách nào để xử lý các tham số tùy chọn trong Moose?

Trình biên dịch phàn nàn rằng "Không thể sửa đổi cuộc gọi chương trình con không phải lvalue tại dòng Parser.pm 16."

Tôi không hiểu tại sao tôi không thể chỉ định một đối tượng mới. Tôi đoán có một cách tốt hơn hoặc hợp lệ hơn để làm các tham số tùy chọn với 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

Tôi không thấy bất kỳ kết nối nào với thông số tùy chọn. Bạn có thể mở rộng về điều đó? – ysth

Trả lời

13

$self->mech là cuộc gọi phương thức; bạn không thể thực sự coi nó như một trường trong cấu trúc C. Nếu bạn muốn thiết lập nó, bạn cần truyền đối tượng mới cho nó.

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

Trong khi Perl đã cung cấp khả năng sử dụng các thuộc tính theo cách mà bạn đang cố gắng để cho một năm nhiều tốt (thông qua những gì được gọi là giá trị trái subs), nó không phải là cái gì đó đang ở trong OO Perl đầu tiên phát hành, và nhân dân khá nhiều việc phải làm mà không có nó. Đặc biệt là kể từ khi thực hiện xác nhận là một chút khôn lanh (và không hiệu quả).

Bạn có thể sử dụng MooseX::Meta::Attribute::Lvalue, nhưng (theo tài liệu) với chi phí không kiểm tra loại trên một số thuộc tính.

Tôi khuyên bạn chỉ nên gắn bó với kiểu $ self-> attribute ("value").

+0

Không sử dụng mô-đun đó, nó bị hỏng bởi thiết kế. –

+0

@Dave Rolsky: theo cách tôi đã chú ý, hoặc theo cách khác? – ysth

6

Có lẽ cách Moose ưa thích để làm điều này là để thiết lập lazy_build trên thuộc tính:

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

này sẽ cho phép các thuộc tính 'mech' để dân cư lần đầu tiên nó được gọi là, trừ trường hợp quy định của constructor hoặc bởi accessor (vì nó vẫn là 'rw').

+0

Cảm ơn bạn đã quay lại câu hỏi này và giải thích của bạn! –

Các vấn đề liên quan