sundar
sundar

Reputation: 456

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 ??

Upvotes: 5

Views: 1409

Answers (2)

brian d foy
brian d foy

Reputation: 132730

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.

Upvotes: 5

mob
mob

Reputation: 118595

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.

Upvotes: 1

Related Questions