2009-12-03 58 views
7

Dưới đây là những gì tôi muốn đạt được:Tôi làm cách nào để xác định lại chương trình con và giữ lại chương trình con cũ?

sub first { 
    print "this is original first"; 
} 

*original_first = \&first; 

sub first { 
    print "this is first redefined"; 
} 

original_first(); # i expect this to print "this is original first" 
first() # i expect this to print "this is first redefined" 

Tôi nghĩ rằng bằng cách tiết kiệm là biểu tượng cho first, tôi muốn có thể sau đó gọi chương trình con gốc (dưới tên original_first) và cũng để có thể để gọi first và nhận số được xác định lại. Tuy nhiên, nếu tôi gọi số original_first, tôi vẫn nhận được thông báo "đây là lần đầu tiên được xác định lại". Tôi phải làm gì để thực hiện công việc này?

Trả lời

9

này nên làm việc như bạn mong đợi:

sub first { 
    print "this is original first"; 
} 

*original_first = \&first; 

*first = sub { 
    print "this is first redefined"; 
}; 
+0

Có thể, khi bạn xác định lại biểu tượng 'đầu tiên', chỉ ảnh hưởng đến phần mã? – Geo

+5

việc gán một coderef (được tạo bởi sub {...}) vào một typeglob sẽ chỉ thay thế mục CODE trong glob. bất kỳ kiểu dữ liệu nào khác trong glob sẽ không thay đổi –

+4

Bạn cũng có thể sử dụng 'local * first = sub {...};' để thay thế hàm chỉ trong khối cụ thể. –

9

trong mã của bạn, Perl giải thích cả hai tờ khai phụ tương tự như sau:

BEGIN { 
    *first = sub { ... } 
} 

vì vậy cả hai công việc để &first cuối lên xảy ra trước khi lưu bản sao và gọi các thói quen. sửa chữa là đưa tuyên bố thứ hai vào một nhiệm vụ thời gian chạy:

sub first { 
    print "this is original first"; 
} 

*original_first = \&first; 

*first = sub {print "this is first redefined"}; 

original_first(); # prints "this is original first" 
first();   # prints "this is first redefined" 
+0

Giải thích hay. Cảm ơn! – Geo

+0

trích dẫn cần thiết cho hành vi 'sub {}' -> 'BEGIN {* ...}' mà bạn mô tả. – Ether

+0

tôi đang suy luận ở trên từ giải thích sau đây từ perlmod: Định nghĩa chương trình con (và khai báo, cho rằng vấn đề) không nhất thiết phải nằm trong gói có bảng biểu tượng mà chúng chiếm. Bạn có thể định nghĩa chương trình con bên ngoài gói của nó bằng cách rõ ràng đủ điều kiện tên của chương trình con: 1. gói chính; 2. sub Some_package :: foo {...} # & foo được định nghĩa trong Some_package Đây chỉ là một cách viết tắt cho một bài tập typeglob tại thời gian biên dịch: 1. BEGIN {* Some_package :: foo = sub {... }} –

1

Xem mô-đun Hook::LexWrap, có thể xử lý tất cả điều đó cho bạn. Nếu bạn không muốn sử dụng các mô-đun, chỉ cần nhìn vào nguồn, trong đó cho bạn thấy chính xác làm thế nào để làm điều đó.

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