Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl Inheritance - Who's the caller of the Parent Class

I have a situation where I need to find the caller of a package and my code looks something like:

Inherited.pm:

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

BaseClass.pm

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

Now I have another class (MyClass.pm) which does:
MyClass.pm:

$obj = Inherited->new();  

This prints Inherited. But I need MyClass to be the printed statement.

Could someone please help me out on how to solve this ??

like image 553
sundar Avatar asked Apr 04 '12 13:04

sundar


2 Answers

When you give caller an argument, you tell it how many levels to go back. You've given it the argument 0, which is the current level. If you want one level up, add 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;
    }

Now the result is:

0: Inherited
1: MyClass

Remember to always include complete example programs in your questions. The Perl code you posted was broken for various other reasons unrelated to caller.

like image 127
brian d foy Avatar answered Oct 17 '22 15:10

brian d foy


If I'm reading your post correctly, you need to find the last frame in the call stack that is calling a constructor.

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

or

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

The second code snippet will handle the case when there are intermediate function calls that are not constructors, e.g., if the call stack looks like

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

the first snippet would return the caller for Inherited::new (which presumably would be GrandChild, and the second one would return the caller of GrandChild::new.

like image 28
mob Avatar answered Oct 17 '22 14:10

mob