2012-04-04 22 views
5

Tôi có một tình huống mà tôi cần phải tìm ra người gọi của một gói và mã của tôi trông giống như sau:Perl Inheritance - Ai là người gọi của tầng lớp phụ huynh

Inherited.pm:

package Inherited; 
our @ISA = qw(BaseClass); 
sub new { 
    SUPER::new(); 
} 

BaseClass .pm

package BaseClass; 
sub new { 
    $a = caller(0); 
    print $a 
} 

Bây giờ tôi có một lớp (MyClass.pm) mà hiện:
MyClass.pm:

$obj = Inherited->new(); 

Bản in này được kế thừa. Nhưng tôi cần MyClass để làm bản in.

Ai đó có thể giúp tôi giải quyết vấn đề này không?

+0

Tôi không hiểu tại sao bạn mong đợi điều này. 'Inherited' là người gọi. Bạn có thể kiểm tra trong 'new()' của 'Inherited' và sau đó chuyển thông tin đó vào. – Cfreak

+0

@Cfreak: cảm ơn bạn đã phản hồi. Ya tôi chấp nhận rằng đi qua đối số là một giải pháp, nhưng có cách nào khác để tìm người gọi của lớp cha mẹ. Trong kịch bản thực tế của tôi, tôi cần loại chức năng này mà không cần truyền tham số. – sundar

+0

Bạn có thể sử dụng khả năng stack-trace của 'Carp' để tìm kiếm toàn bộ danh sách người gọi ('Carp :: longmess()') nhưng nó không phải là một giải pháp tuyệt vời. Xem qua các mô-đun 'Class :: *' trên CPAN. Có thể có một giải pháp thanh lịch hơn ở đó. – Cfreak

Trả lời

5

Khi bạn cung cấp cho đối số caller, bạn cho biết có bao nhiêu cấp để quay lại. Bạn đã cho nó đối số 0, là cấp độ hiện tại. Nếu bạn muốn một mức lên, thêm 1:

use v5.12; 

package Inherited { 
    our @ISA = qw(BaseClass); 
    sub new { 
     $_[0]->SUPER::new(); 
    } 
} 

package BaseClass { 
    sub new { 
     say "0: ", scalar caller(0); 
     say "1: ", scalar caller(1); 
    } 
} 

package MyClass { 
    my $obj = Inherited->new; 
    } 

Bây giờ kết quả là:

0: Inherited 
1: MyClass 

Hãy nhớ luôn luôn bao gồm các chương trình ví dụ hoàn chỉnh trong các câu hỏi của bạn. Mã Perl bạn đăng đã bị hỏng vì nhiều lý do khác không liên quan đến caller.

+0

Tôi nghĩ rằng mô-đun Cá chép làm một cái gì đó như thế này: nếu người gọi là "liên quan" với kẻ làm bánh, nó bỏ qua đến người gọi tiếp theo để thay thế. – Konerak

+0

cảm ơn phản hồi của bạn. Nó hiểu cách người gọi làm việc. – sundar

1

Nếu tôi đọc bài viết của bạn một cách chính xác, bạn cần phải tìm khung cuối cùng trong ngăn xếp cuộc gọi đang gọi một hàm tạo.

package BaseClass; 
sub new { 
    my $a = caller(0); 
    for (my $n=0; my @c=caller($n); $n++) { 
     last if $c[4] !~ /::new$/; 
     $a = $c[0]; 
    } 
    print $a; 
} 

hoặc

package BaseClass; 
sub new { 
    my @a; 
    unshift @a, [ caller(@a) ] while caller(@a); 
    my ($a) = grep { $_->[4] =~ /::new$/ } @a; 
    print $a // caller(0); 
} 

Đoạn mã thứ hai sẽ xử lý các trường hợp khi có những cuộc gọi chức năng trung gian mà không phải là nhà xây dựng, ví dụ, nếu các cuộc gọi stack trông giống như

GrandChild::new 
GrandChild::init 
Inherited::new 
BaseClass::new 

sự đoạn mã đầu tiên sẽ trả về người gọi cho Inherited::new (có thể là GrandChild và đoạn thứ hai sẽ trả lại người gọi là GrandChild::new.

+0

cảm ơn phản hồi. Giải pháp của bạn cũng đang làm việc cho tôi nhưng đáng buồn là tôi không thể chấp nhận nhiều câu trả lời ở đây. – sundar

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