2011-09-11 19 views
13

Puns sang một bên, tôi đang cố gắng thực hiện một phương thức import trong lớp Perl của tôi để khởi tạo đối tượng Data, về cơ bản là một mảng được tôn vinh của hashrefs. .Chết tiệt, Perl không thể ban phước cho đối tượng của tôi

Dưới đây là một ví dụ về làm thế nào tôi có kế hoạch để sử dụng nó:

# Pull in the data 
my $data = Data->import(
         [ 
          { a => 1, b => 7, c => 3}, 
          { a => 7, b => 9, c => 2}, 
         ] 
         ); 

$data->manipulate; # Use package methods 

thực hiện import của tôi là như sau:

package Data; 

sub initialize { 
    my $class = shift; 
    my $data = []; 
    bless $data, $class; 
    return $data; 
} 

sub import { 

    my ($class, $data) = @_; 

    bless $data, $class; 
    return $data; 
} 

1; 

Điều đáng ngạc nhiên là Perl báo cáo lỗi tại biên dịch -time (lưu ý khối BEGIN):

Can't bless non-reference value at Data.pm line 51. 
BEGIN failed--compilation aborted at myScript.pl line 8. 

perldiag không thêm nhiều rõ ràng với những gì đang xảy ra:

Can't bless non-reference value

(F) Only hard references may be blessed. This is how Perl "enforces" encapsulation of objects. See perlobj .


Tôi thậm chí đã cố gắng khởi tạo các đối tượng và bổ sung các dữ liệu theo hai bước riêng biệt:

sub import {       #< Another constructor > 

    my ($class, $data) = @_; 

    my $obj = $class->initialize; 
    push @$obj, @$data; 

    return $obj; 
} 

Điều này dẫn đến lỗi biên dịch sau:

Can't use an undefined value as an ARRAY reference... 
BEGIN failed--compilation aborted at... 

Hai câu hỏi:

  1. Có gì sai với những gì tôi đã làm gì?
  2. Có thể ai đó vui lòng làm rõ giải thích perldiag về lỗi biên dịch này không?
+0

Cảnh báo: Có tham chiếu nào tốt hơn 'perldiag' để hiểu thông báo cảnh báo/lỗi không? – Zaid

+2

Nói chung, bạn có thể tấn công các lỗi như thế này bằng cách chèn một bản in các điều kiện tiên quyết của bạn. Trong trường hợp này, các đối số cho chương trình con của bạn. ('in 'nhập khẩu đã nhận: @_ \ n"; ') Điều đó sẽ cho bạn biết rằng những gì bạn nghĩ là một mảng thực sự là không. Tiếp theo, thêm một bảo vệ, một cái gì đó như 'ref $ data eq 'ARRAY' hoặc thú nhận" không phải là mảng: '$ data' ";' và bạn sẽ tìm ra nơi mà cuộc gọi vi phạm đến từ đó. ('confess' là từ' sử dụng Carp 'thú nhận'; 'và cung cấp một backtrace đầy đủ) Giữ dòng đó, vì nó có thể giúp bạn ngay lập tức bắt các lỗi khác trong tương lai, có lẽ thay đổi' confess' thành 'croak'. –

+0

@Lance Roberts: Tiêu đề ban đầu là cách chơi trên các từ trong tham chiếu đến mô-đun ['Acme :: Damn'] (http://search.cpan.org/perldoc?Acme::Damn) (ngược lại với 'bless') – Zaid

Trả lời

21

nhập() là tên nguy hiểm để đưa ra một phương pháp, vì đôi khi Perl gọi phương thức được gọi là 'nhập' cho bạn. Trong thực tế, tuyên bố:

use Data; 

thực sự có nghĩa là:

BEGIN { 
    require Data; 
    Data->import(); 
} 

đó xảy ra trong 'biên soạn'.

Vì vậy, có khả năng phương thức import() của bạn đang được Perl gọi là một phần của cơ chế tải lớp trước khi bạn có cơ hội sử dụng nó. Bạn nên đổi tên phương thức import() của bạn thành phương thức khác (ví dụ: import_data) và bạn sẽ ổn.

+0

Nếu đúng như vậy, anh ta sẽ không gặp lỗi anh ta mắc phải. –

+3

Vâng, anh ta sẽ làm vậy. Trong cả hai trường hợp, Perl sẽ gọi Data-> import(), vì vậy dữ liệu $ không bao giờ tồn tại, gây ra lỗi 'no object to bless' và lỗi 'no array to dereference'. – Alex

+0

+1: Đây là vấn đề, được đổi tên thành 'import' thành' load'. Sự tỉnh táo của tôi đã được phục hồi. Cảm ơn! – Zaid

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